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.

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:
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 $USERConfirme a instalação:
docker --version
docker compose versionPasso 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: dbaponta para o serviçodbpelo 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_dataewp_data) são o que faz seus dados sobreviverem a umdocker compose down. Tire-os e você tem um WordPress descartável.
Variáveis de ambiente essenciais
| Variável | Serviço | Para que serve |
|---|---|---|
WORDPRESS_DB_HOST | wordpress | host do banco (o nome do serviço, ex.: db) |
WORDPRESS_DB_NAME | wordpress | nome do banco que o WordPress usa |
WORDPRESS_DB_USER | wordpress | usuário do banco |
WORDPRESS_DB_PASSWORD | wordpress | senha desse usuário |
MARIADB_DATABASE | db | cria o banco no primeiro start |
MARIADB_USER / MARIADB_PASSWORD | db | cria o usuário e a senha do banco |
MARIADB_ROOT_PASSWORD | db | senha 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-forteGere 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:
| Aspecto | Desenvolvimento (local) | Produção |
|---|---|---|
| Acesso | http://localhost:8080 | domínio real com HTTPS |
| HTTPS | dispensável | obrigatório, via reverse proxy (Nginx, Traefik ou Caddy) + Let's Encrypt |
| Arquivos do site | bind mount para editar tema/plugin no editor | volume nomeado (só o container escreve) |
| Porta do banco | pode expor para inspecionar | não expor a 3306 para fora |
| Senhas | simples, no .env | fortes, em gerenciador de segredos |
| Backup | opcional | mysqldump + 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:roNo 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: wordpressE rode comandos pontuais com run --rm:
docker compose run --rm wpcli wp core version
docker compose run --rm wpcli wp plugin listA 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).sqlPara restaurar:
docker compose exec -T db sh -c \
'mysql -u wordpress -p"$MARIADB_PASSWORD" wordpress' < backup-2026-07-17.sqlO 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
| Problema | Causa provável | O que fazer |
|---|---|---|
| Error establishing a database connection | banco ainda subindo ou senha divergente | conferir as senhas no .env e esperar o db ficar pronto (docker compose logs db) |
| Site "perdeu tudo" ao recriar o container | falta de volume nomeado | declarar wp_data e db_data em volumes: (causa nº 1 de perda de dados) |
| Porta 8080 já em uso | outro serviço ocupando a porta | trocar o mapeamento para "8081:80" |
Redireciona para http ou dá mixed content | site atrás de proxy HTTPS sem config | definir WP_HOME/WP_SITEURL e passar X-Forwarded-Proto no proxy |
| Volume crescendo sem parar | logs e imagens antigas acumulando | docker 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.


