Buscar

WordPress com Docker: Guia de Instalação e Deploy

Como rodar o WordPress com Docker usando as imagens oficiais e o Docker Compose v2 — o compose mínimo que funciona, volumes para não perder dados e o que muda na hora de ir para produção.

Gabriel Pedroso12 min de leitura
WordPress com Docker

Rodar o WordPress com Docker resolve o clássico "na minha máquina funciona": o mesmo docker-compose.yml sobe um ambiente idêntico no seu notebook, no staging e no servidor. Mas o detalhe que separa um setup sério de uma dor de cabeça é um só — os volumes. Sem eles, um docker compose down leva junto o banco, os uploads e o site inteiro.

Este guia vai do compose mínimo que já funciona até o que muda na hora de colocar no ar: as imagens oficiais, a persistência de dados, as variáveis de ambiente e o caminho de produção com HTTPS e backup. Se você ainda não conhece os conceitos básicos, vale ler antes o que é Docker e o Docker para iniciantes. O fluxo do começo ao fim é este:

1docker-compose.ymldefine dois serviços: wordpress e um banco (mysql ou mariadb)
2Imagens oficiaiso Docker baixa wordpress e mariadb/mysql do Docker Hub
3Volumeswp_data e db_data guardam site e banco fora do container
4docker compose up -dos containers sobem e o WordPress conecta no banco
5localhost:8080você abre o wp-admin e conclui a instalação
O caminho é curto: você descreve os serviços num arquivo, o Docker baixa as imagens oficiais, os volumes guardam site e banco fora do container, e um único comando sobe tudo.

Por que Docker para WordPress

Um container compartilha o kernel do host e sobe em segundos, em vez de virtualizar um sistema operacional inteiro como uma máquina virtual. Na prática, isso te dá três coisas que importam para o WordPress:

  • Ambiente consistente: a versão do PHP, do banco e do WordPress é a mesma em dev e em produção. Fim do "funciona só no meu computador".
  • Isolamento: cada projeto tem seu próprio PHP e banco, sem conflito entre sites na mesma máquina.
  • Reprodutível: o docker-compose.yml é a documentação viva do stack — quem clonar o repositório sobe tudo igual.

O ponto que costuma pegar quem está começando é justamente o oposto do isolamento: por padrão, tudo que o container escreve some quando ele é recriado. É aí que entram os volumes, e é por isso que eles aparecem em quase todo passo daqui para frente.

Passo 1: Instalar o Docker

O Docker Desktop (Mac e Windows) e o instalador de Linux já trazem o Docker Compose v2 embutido — o subcomando docker compose, com espaço. O binário antigo docker-compose (com hífen) está descontinuado; não precisa instalar nada à parte.

Mac e Windows: baixe o Docker Desktop em docker.com/products/docker-desktop e instale. No Windows, ative o WSL 2 quando o instalador pedir.

Linux (Ubuntu/Debian):

# Instala o Docker Engine + o plugin do Compose v2
curl -fsSL https://get.docker.com | sh

# Roda o docker sem sudo (relogue depois)
sudo usermod -aG docker $USER

Confirme a instalação:

docker --version
docker compose version

Passo 2: O compose mínimo que funciona

Aqui está a diferença mais importante em relação a tutoriais antigos: você não precisa construir uma imagem do zero. As imagens oficiais do WordPress no Docker Hub já vêm com PHP, Apache e o WordPress instalados. Bastam dois serviços — o WordPress e um banco — mais os volumes.

Crie uma pasta para o projeto e, dentro dela, um arquivo docker-compose.yml:

services:
  db:
    image: mariadb:11
    restart: always
    environment:
      MARIADB_DATABASE: wordpress
      MARIADB_USER: wordpress
      MARIADB_PASSWORD: ${DB_PASSWORD}
      MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql

  wordpress:
    image: wordpress:php8.3-apache
    restart: always
    depends_on:
      - db
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wp_data:/var/www/html

volumes:
  db_data:
  wp_data:

Três detalhes que valem explicar:

  • Não tem version: no topo. No Compose v2, esse campo é obsoleto e só gera aviso — pode esquecer dele.
  • WORDPRESS_DB_HOST: db aponta para o serviço db pelo nome. O Compose cria uma rede automática entre os dois serviços; não precisa declarar rede nem porta do banco à mão.
  • Os dois volumes na base (db_data e wp_data) são o que faz seus dados sobreviverem a um docker compose down. Tire-os e você tem um WordPress descartável.

Variáveis de ambiente essenciais

VariávelServiçoPara que serve
WORDPRESS_DB_HOSTwordpresshost do banco (o nome do serviço, ex.: db)
WORDPRESS_DB_NAMEwordpressnome do banco que o WordPress usa
WORDPRESS_DB_USERwordpressusuário do banco
WORDPRESS_DB_PASSWORDwordpresssenha desse usuário
MARIADB_DATABASEdbcria o banco no primeiro start
MARIADB_USER / MARIADB_PASSWORDdbcria o usuário e a senha do banco
MARIADB_ROOT_PASSWORDdbsenha do root do banco

Se preferir o MySQL, troque a imagem por mysql:8.0 e as variáveis MARIADB_* pelas equivalentes MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD e MYSQL_ROOT_PASSWORD. O WordPress roda igual nas duas.

Passo 3: O arquivo .env

Não deixe senha cravada no docker-compose.yml. Crie um .env na mesma pasta:

DB_PASSWORD=troque-por-uma-senha-forte
DB_ROOT_PASSWORD=troque-por-outra-senha-forte

Gere senhas de verdade com openssl rand -base64 24 e adicione o .env ao .gitignore para não vazar segredo no repositório. Em produção, o ideal é guardar essas variáveis num gerenciador de segredos em vez de um arquivo em texto.

Passo 4: Subir e acessar

Da pasta do projeto:

docker compose up -d      # sobe os containers em segundo plano
docker compose ps         # confere o status
docker compose logs -f    # acompanha os logs (Ctrl+C para sair)

Abra http://localhost:8080, escolha o idioma, preencha o título do site e o usuário administrador, e conclua a instalação. É o mesmo assistente do WordPress instalado na unha — a diferença é que aqui o ambiente inteiro sobe e desce com um comando.

Para parar sem apagar nada, use docker compose down. Nunca rode docker compose down -v a menos que queira apagar os volumes: o -v é exatamente o que destrói wp_data e db_data.

Passo 5: Dev × produção — o que muda

O compose acima já é suficiente para desenvolver. Para colocar no ar, alguns pontos mudam:

AspectoDesenvolvimento (local)Produção
Acessohttp://localhost:8080domínio real com HTTPS
HTTPSdispensávelobrigatório, via reverse proxy (Nginx, Traefik ou Caddy) + Let's Encrypt
Arquivos do sitebind mount para editar tema/plugin no editorvolume nomeado (só o container escreve)
Porta do bancopode expor para inspecionarnão expor a 3306 para fora
Senhassimples, no .envfortes, em gerenciador de segredos
Backupopcionalmysqldump + volume, automatizado

Na prática, você mantém os mesmos dois serviços e coloca um reverse proxy na frente para cuidar do HTTPS. Se o WordPress fica atrás de um proxy que termina o TLS, avise-o disso para não gerar redirecionamento em loop nem mixed content — passe o header X-Forwarded-Proto no proxy e, se preciso, fixe as URLs com WORDPRESS_CONFIG_EXTRA:

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

Para acompanhar containers, logs e volumes por uma interface web em vez do terminal, o Portainer ajuda bastante em servidores de produção.

Passo 6: Apache ou PHP-FPM + Nginx?

A imagem wordpress:php8.3-apache traz o Apache junto e serve o site direto na porta 80 — é a escolha mais simples e cobre a maioria dos casos. Quando você quer controle fino sobre o servidor web (regras de cache, headers, limites de upload), a alternativa é a imagem wordpress:php8.3-fpm, que só roda o PHP na porta 9000 e precisa de um Nginx na frente:

  wordpress:
    image: wordpress:php8.3-fpm
    volumes:
      - wp_data:/var/www/html
    # ...mesmas variáveis de banco...

  nginx:
    image: nginx:alpine
    depends_on:
      - wordpress
    ports:
      - "8080:80"
    volumes:
      - wp_data:/var/www/html:ro
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro

No nginx.conf, a peça central é passar o PHP para o container do WordPress com fastcgi_pass wordpress:9000;. Para desenvolver, não há motivo para essa complexidade — comece pela imagem Apache e só migre para o par FPM + Nginx quando tiver uma necessidade concreta.

Passo 7: WP-CLI dentro do Docker

Um detalhe que confunde: as imagens apache e fpm não trazem o WP-CLI. Para usá-lo, o WordPress publica uma imagem separada, wordpress:cli. Adicione um serviço apontando para o mesmo volume:

  wpcli:
    image: wordpress:cli
    depends_on:
      - db
      - wordpress
    volumes:
      - wp_data:/var/www/html
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
      WORDPRESS_DB_NAME: wordpress

E rode comandos pontuais com run --rm:

docker compose run --rm wpcli wp core version
docker compose run --rm wpcli wp plugin list

A imagem cli roda como www-data; se topar com erro de permissão no volume compartilhado, ajuste o user: do serviço para casar com o dono dos arquivos.

Passo 8: Backup

São duas frentes — o banco e o conteúdo do site. Para o banco, rode o mysqldump dentro do próprio container do db (a senha já está no ambiente dele):

docker compose exec db sh -c \
  'mysqldump -u wordpress -p"$MARIADB_PASSWORD" wordpress' > backup-$(date +%F).sql

Para restaurar:

docker compose exec -T db sh -c \
  'mysql -u wordpress -p"$MARIADB_PASSWORD" wordpress' < backup-2026-07-17.sql

O conteúdo do site (uploads, temas e plugins) vive no volume wp_data. O Compose prefixa o nome do volume com o nome da pasta do projeto, então empacote-o assim (ajuste wordpress-docker para o nome da sua pasta):

docker run --rm \
  -v wordpress-docker_wp_data:/data \
  -v "$PWD":/backup \
  alpine tar czf /backup/wp_data-$(date +%F).tgz -C /data .

Guarde os dois arquivos juntos e fora do servidor. E teste a restauração de tempos em tempos: backup que nunca foi restaurado é só uma esperança.

Solução de problemas comuns

ProblemaCausa provávelO que fazer
Error establishing a database connectionbanco ainda subindo ou senha divergenteconferir as senhas no .env e esperar o db ficar pronto (docker compose logs db)
Site "perdeu tudo" ao recriar o containerfalta de volume nomeadodeclarar wp_data e db_data em volumes: (causa nº 1 de perda de dados)
Porta 8080 já em usooutro serviço ocupando a portatrocar o mapeamento para "8081:80"
Redireciona para http ou dá mixed contentsite atrás de proxy HTTPS sem configdefinir WP_HOME/WP_SITEURL e passar X-Forwarded-Proto no proxy
Volume crescendo sem pararlogs e imagens antigas acumulandodocker system prune (com cuidado — leia o que ele vai apagar)

Perguntas frequentes sobre WordPress com Docker

Preciso de Docker para rodar o WordPress?

Não é obrigatório — dá para instalar o WordPress direto num servidor com PHP e MySQL. Mas o Docker garante que o ambiente do seu notebook seja idêntico ao de produção, facilita compartilhar o setup com a equipe e deixa subir e derrubar tudo com um comando. Para quem trabalha com mais de um site, compensa muito.

Preciso escrever um Dockerfile ou a imagem oficial já basta?

Na maioria dos casos, a imagem oficial wordpress do Docker Hub já basta — ela vem com o PHP, o Apache e o WordPress prontos. Só vale construir um Dockerfile próprio quando você precisa de extensões PHP extras, do Imagick ou de ferramentas que não vêm na imagem base.

Devo usar volumes nomeados ou bind mounts?

Volumes nomeados (como wp_data) são o padrão para persistir dados e são mais rápidos, principalmente no Mac e no Windows — use-os para o banco e para produção. Bind mounts, que apontam para uma pasta do host, são úteis em desenvolvimento, quando você quer editar um tema ou plugin direto no seu editor.

Dá para usar Docker Compose em produção?

Dá, e é uma opção legítima para um site único num servidor dedicado ou VPS. Para escalar horizontalmente (várias réplicas, balanceamento, alta disponibilidade), aí sim vale um orquestrador como o Docker Swarm ou o Kubernetes. Para a maioria dos projetos, um Compose bem feito com HTTPS e backup resolve.

Como faço backup de um WordPress rodando em Docker?

São duas coisas: o banco de dados, com mysqldump rodando dentro do container do banco, e o conteúdo do site (uploads, temas e plugins), que fica no volume wp_data. Faça backup dos dois juntos, guarde uma cópia fora do servidor e teste a restauração de vez em quando — backup que nunca foi restaurado não é backup.

Conclusão

Rodar o WordPress com Docker não precisa ser complicado: dois serviços, as imagens oficiais e — o ponto que não dá para pular — os volumes que guardam site e banco. Comece pela imagem Apache no seu ambiente local, valide o fluxo e só então adicione as camadas de produção: HTTPS por um reverse proxy, senhas fortes e backup automatizado.

Com essa base no ar, os próximos passos naturais são reforçar a segurança do WordPress e afinar o SEO para WordPress. O container é o meio; o site que ele serve é o que importa.