Docker WordPress com MySQL compartilhado

Vantagens desta configuração

  1. MySQL único: economiza recursos, mais fácil de fazer backup
  2. Isolamento: cada WordPress roda em container separado
  3. Escalabilidade: adicionar novos sites é rápido
  4. Segurança: containers não expostos diretamente (apenas localhost)
  5. Manutenção: atualizar WordPress individualmente sem afetar outros

Habilite os módulos necessários no Apache:

a2enmod headers proxy proxy_http rewrite
systemctl restart apache2

1. MySQL compartilhado

Crie /opt/mysql/docker-compose.yml:

services:
  mysql:
    image: mysql:8.0
    container_name: mysql-shared
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root_password_forte_aqui
    volumes:
      - ./data:/var/lib/mysql
    ports:
      - "127.0.0.1:3306:3306"
    networks:
      - shared-network

networks:
  shared-network:
    name: shared-network
    driver: bridge

Inicie o MySQL:

cd /opt/mysql
docker compose up -d

Crie os bancos de dados para cada site:

docker exec -it mysql-shared mysql -uroot -p

Dentro do MySQL:

CREATE DATABASE site1_wp;
CREATE DATABASE site2_wp;
CREATE DATABASE site3_wp;

CREATE USER 'site1_user'@'%' IDENTIFIED BY 'senha_site1';
CREATE USER 'site2_user'@'%' IDENTIFIED BY 'senha_site2';
CREATE USER 'site3_user'@'%' IDENTIFIED BY 'senha_site3';

GRANT ALL PRIVILEGES ON site1_wp.* TO 'site1_user'@'%';
GRANT ALL PRIVILEGES ON site2_wp.* TO 'site2_user'@'%';
GRANT ALL PRIVILEGES ON site3_wp.* TO 'site3_user'@'%';

FLUSH PRIVILEGES;
EXIT;

2. WordPress Site 1

Crie /opt/wordpress/site1/docker-compose.yml:

services:
  wordpress:
    image: wordpress:latest
    container_name: wp-site1
    restart: always
    ports:
      - "127.0.0.1:8081:80"
    environment:
      WORDPRESS_DB_HOST: mysql-shared:3306
      WORDPRESS_DB_NAME: site1_wp
      WORDPRESS_DB_USER: site1_user
      WORDPRESS_DB_PASSWORD: senha_site1
    volumes:
      - ./html:/var/www/html
    networks:
      - shared-network

networks:
  shared-network:
    external: true
cd /opt/wordpress/site1
docker compose up -d

3. WordPress Site 2

Crie /opt/wordpress/site2/docker-compose.yml:

services:
  wordpress:
    image: wordpress:latest
    container_name: wp-site2
    restart: always
    ports:
      - "127.0.0.1:8082:80"
    environment:
      WORDPRESS_DB_HOST: mysql-shared:3306
      WORDPRESS_DB_NAME: site2_wp
      WORDPRESS_DB_USER: site2_user
      WORDPRESS_DB_PASSWORD: senha_site2
    volumes:
      - ./html:/var/www/html
    networks:
      - shared-network

networks:
  shared-network:
    external: true
cd /opt/wordpress/site2
docker compose up -d

4. Apache – VirtualHosts separados

Site 1: /etc/apache2/sites-available/site1.conf

<VirtualHost *:80>
    ServerName site1.com.br
    ServerAlias www.site1.com.br

    ProxyPreserveHost On
    ProxyRequests Off

    ProxyPass        / http://127.0.0.1:8081/
    ProxyPassReverse / http://127.0.0.1:8081/

    RequestHeader set X-Forwarded-Proto "http"
    RequestHeader set X-Forwarded-Host  "%{HTTP_HOST}e"

    ErrorLog  ${APACHE_LOG_DIR}/site1_error.log
    CustomLog ${APACHE_LOG_DIR}/site1_access.log combined
</VirtualHost>

Site 2: /etc/apache2/sites-available/site2.conf

<VirtualHost *:80>
    ServerName site2.com.br
    ServerAlias www.site2.com.br

    ProxyPreserveHost On
    ProxyRequests Off

    ProxyPass        / http://127.0.0.1:8082/
    ProxyPassReverse / http://127.0.0.1:8082/

    RequestHeader set X-Forwarded-Proto "http"
    RequestHeader set X-Forwarded-Host  "%{HTTP_HOST}e"

    ErrorLog  ${APACHE_LOG_DIR}/site2_error.log
    CustomLog ${APACHE_LOG_DIR}/site2_access.log combined
</VirtualHost>

Ative os sites:

a2ensite site1.conf
a2ensite site2.conf
apache2ctl configtest
systemctl reload apache2

5. SSL para múltiplos sites

certbot --apache -d site1.com.br -d www.site1.com.br
certbot --apache -d site2.com.br -d www.site2.com.br

O Certbot ajusta o VirtualHost automaticamente e adiciona o redirect HTTP→HTTPS.

Depois, atualize o RequestHeader para HTTPS:

RequestHeader set X-Forwarded-Proto "https"

6. Corrigir URLs do WordPress atrás de proxy

No wp-config.php (dentro de ./html/) adicione antes de /* That's all */:

define('WP_HOME',    'https://seudominio.com.br');
define('WP_SITEURL', 'https://seudominio.com.br');

// Necessário para que o WordPress reconheça o proxy
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

7. Verificação rápida

# Containers rodando?
docker compose ps

# Porta 8080 escutando só no localhost?
ss -tlnp | grep 8080

# Apache do host OK?
systemctl status apache2
curl -I http://seudominio.com.br

Comandos úteis

# Ver todos os sites rodando
docker ps

# Logs de um site específico
docker logs wp-site1

# Parar/iniciar um site
cd /opt/wordpress/site1
docker compose down
docker compose up -d

# Backup do MySQL (todos os bancos)
docker exec mysql-shared mysqldump -uroot -p --all-databases > backup-$(date +%F).sql

A edição dos parâmetros do PHP pode ser feita no arquivo .htaccess. Exemplo:

php_value upload_max_filesize 64M
php_value post_max_size 64M
php_value memory_limit 128M
php_value max_execution_time 300
php_value max_input_time 300

Migrando um site WordPress

Existem várias formas de migrar um site em WordPress entre servidores diferentes.

Aqui seguem alguns passos sobre uma forma de executar esse processo.

  1. Certifique-se de que o sistema de recuperação de senha está funcionando no site origem. Após a migração a conta do administrador pode sofrer alteração de senha e você pode ficar com dificuldade em logar novamente no servidor destino.
  2. Instalar o plugin UpdraftPlus WordPress Backup na origem. Esse plugin também poderá ser usado para backup com armazenamento nos serviços de nuvem.
  3. Faça um backup dentro desse plugin em Backup/Restauração.
  4. Em Backups Existentes, baixe o arquivo de cada recurso para sua máquina local (Banco de dados, Plugins, Temas, etc).
  5. No servidor destino, crie um site padrão WordPress que vai receber o backup. Atenção para o detalhe da senha do administrador que será alterada após a restauração do backup para o valor usado no site de origem.
  6. Altere o registro DNS para apontar para o IP do servidor destino.
  7. Ative a versão ssl do site com o comando:
    certbot –apache –redirect -d site.com -m user@mail.com –agree-tos
  8. Acesse o site destino e instale o plugin UpdraftPlus WordPress Backup.
  9. Enviar os arquivos de backup para o servidor e executar a restauração.
  10. Deletar as pasta antigas (delete old folders).
  11. Verifique se os links estão funcionando. Caso necessário, altere os links permanentes para o formato padrão.

Permissões para pastas e arquivos do WordPress

Após uma instalação manual do WordPress onde baixamos o pacote e criamos um banco de dados vazio para o instalador gerar os dados, os comandos abaixo deixarão os direitos de acesso às pastas e arquivos da melhor forma possível considerando funcionalidade e segurança.

chown -R www-data:www-data .
find . -type f -exec chmod 644 {} +
find . -type d -exec chmod 755 {} +
mv wp-config-sample.php wp-config.php
chmod 640 wp-config.php

Após esses comandos podemos prosseguir com a instalação do WordPress alterando os dados de acesso ao banco de dados no arquivo wp-config.php.