DevOps 12 мин чтения

Docker Compose для WordPress

Правильный docker-compose.yml для WordPress в продакшне: Nginx, MariaDB, Redis, SSL, автобэкапы. Готовый стек для деплоя.

Docker Compose позволяет описать весь стек WordPress (PHP, Nginx, MySQL, Redis) в одном файле и запустить одной командой. Идеально для разработки и продакшна.

Базовый docker-compose.yml

version: '3.8'

services:
  # База данных
  db:
    image: mariadb:11
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    restart: unless-stopped
    healthcheck:
      test: ['CMD', 'healthcheck.sh', '--connect', '--innodb_initialized']
      interval: 10s
      timeout: 5s
      retries: 5

  # WordPress
  wordpress:
    image: wordpress:php8.2-fpm
    depends_on:
      db:
        condition: service_healthy
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: ${MYSQL_DATABASE}
      WORDPRESS_DB_USER: ${MYSQL_USER}
      WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
      WORDPRESS_CONFIG_EXTRA: |
        define('WP_REDIS_HOST', 'redis');
        define('WP_REDIS_PORT', 6379);
        define('WP_HOME', 'https://${DOMAIN}');
        define('WP_SITEURL', 'https://${DOMAIN}');
    volumes:
      - wordpress_data:/var/www/html
      - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    restart: unless-stopped

  # Nginx
  nginx:
    image: nginx:alpine
    depends_on:
      - wordpress
    ports:
      - '80:80'
      - '443:443'
    volumes:
      - wordpress_data:/var/www/html:ro
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
      - nginx_logs:/var/log/nginx
    restart: unless-stopped

  # Redis
  redis:
    image: redis:7-alpine
    command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
    volumes:
      - redis_data:/data
    restart: unless-stopped

volumes:
  db_data:
  wordpress_data:
  redis_data:
  nginx_logs:

Конфиг Nginx (nginx.conf)

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate     /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;

    root /var/www/html;
    index index.php;

    # Статика с кешем
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        try_files $uri =404;
    }

    # WordPress
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # PHP-FPM
    location ~ \.php$ {
        fastcgi_pass wordpress:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_read_timeout 300;
    }

    # Безопасность
    location ~ /\. { deny all; }
    location = /xmlrpc.php { deny all; }
    location ~* /wp-config.php { deny all; }
}

# HTTP → HTTPS редирект
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

PHP настройки (uploads.ini)

file_uploads = On
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300
max_input_vars = 3000

.env файл

DOMAIN=example.com
MYSQL_ROOT_PASSWORD=supersecretpassword
MYSQL_DATABASE=wordpress
MYSQL_USER=wp_user
MYSQL_PASSWORD=userpassword

Запуск и управление

# Первый запуск
docker compose up -d

# Просмотр логов
docker compose logs -f wordpress
docker compose logs -f nginx

# Перезапуск при изменении конфига
docker compose restart nginx

# Обновление образов
docker compose pull
docker compose up -d

# Бэкап базы данных
docker compose exec db mysqldump -u root -p${MYSQL_ROOT_PASSWORD} ${MYSQL_DATABASE} > backup.sql

Автобэкапы через Cron

# Crontab — бэкап каждую ночь в 3:00
0 3 * * * docker compose -f /path/to/docker-compose.yml exec -T db \
  mysqldump -u root -p${MYSQL_ROOT_PASSWORD} wordpress | \
  gzip > /backups/wp_$(date +%Y%m%d).sql.gz

Советы для продакшна

  1. Используйте .env для секретов, никогда не коммитьте его
  2. Настройте restart: unless-stopped для всех сервисов
  3. Healthcheck для БД предотвращает старт WordPress до готовности MySQL
  4. Тома (volumes) для данных — не теряйте данные при пересборке
  5. Nginx в readonly режиме для файлов WordPress (безопасность)