Esse card é a primeira experiência prática com Docker: subir um WordPress local em duas linhas de comando, sem instalar PHP nem MySQL no Windows. O foco não é WordPress — é entender como o Docker conecta uma pasta do seu computador com o que roda dentro do container, e onde os dados ficam quando você desliga tudo.
A gente tem uma pasta no Windows com a instalação padrão do WordPress: C:\src\PROJETOS\WORDPRESS. Lá dentro tem index.php, wp-admin/, wp-content/ — tudo o que o WordPress precisa. Mas arquivos PHP sozinhos não fazem nada. Pra virar um site no browser, precisa de duas coisas que não estão no Windows:
.php e devolver HTML pro browserInstalar PHP e MySQL no Windows funciona, mas suja a máquina, e cada projeto pode pedir uma versão diferente. A solução com Docker é diferente: a gente aluga esses dois serviços, cada um numa "caixinha" (container), só pelo tempo que precisa.
Em vez de digitar docker run com 20 parâmetros pra cada container, escreve-se um arquivo de texto YAML que descreve a configuração inteira. Coloca o arquivo na pasta do projeto e roda docker compose up -d. Pronto.
services:
wordpress:
image: wordpress:latest
ports:
- "8081:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wp
WORDPRESS_DB_PASSWORD: wp
WORDPRESS_DB_NAME: wordpress
volumes:
- ./:/var/www/html
depends_on:
- db
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wp
MYSQL_PASSWORD: wp
MYSQL_ROOT_PASSWORD: root
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
Duas caixinhas (serviços): uma com WordPress, uma com MySQL. As próximas seções abrem cada bloco do arquivo.
Olhando o bloco services: de cima:
wordpress:latest do Docker Hub. Já vem com Apache + PHP + WordPress instalado lá dentro, prontos pra rodar.mysql:8.0. Já vem com MySQL 8 instalado e configurado.Os nomes que você escolheu (wordpress, db) viram hostnames dentro da rede do Docker. É por isso que o serviço wordpress consegue conversar com o banco usando WORDPRESS_DB_HOST: db:3306 — ele literalmente acessa o outro container pelo nome db. Docker monta uma rede interna automaticamente e cada serviço enxerga os outros pelo nome.
O depends_on: - db diz: "sobe o banco primeiro, depois o WordPress". Sem isso, o WordPress poderia subir antes do banco e quebrar na primeira tentativa de conectar.
Por padrão, container é fechado. Mesmo se Apache estiver rodando lá dentro na porta 80, você não acessa do browser sem abrir uma janela.
ports:
- "8081:80"
Lê-se: "redireciona a porta 8081 do meu Windows pra porta 80 dentro do container". Aí quando você abre http://localhost:8081, o Docker pega esse tráfego e entrega na porta 80 do Apache do container, que processa o PHP e devolve a página.
Se a porta do host (8081) estiver ocupada por outro programa, o up falha com bind: address already in use. Solução: trocar pra outra porta livre.
Repare que o serviço db não tem ports. O banco fica fechado pro mundo, só o WordPress (que está na mesma rede do Docker) consegue acessá-lo. É bom de segurança: ninguém da internet consegue chegar no MySQL.
As imagens oficiais do Docker Hub leem variáveis de ambiente pra se configurar na hora de subir. O bloco environment: define essas variáveis.
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wp
WORDPRESS_DB_PASSWORD: wp
WORDPRESS_DB_NAME: wordpress
Na primeira vez que o container do WordPress sobe, ele detecta que não existe wp-config.php e gera um do zero usando esses valores. Por isso depois da instalação você vai ver o arquivo wp-config.php aparecer dentro da pasta C:\src\PROJETOS\WORDPRESS\ — o container escreveu lá.
O mesmo vale pro MySQL: MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD, MYSQL_ROOT_PASSWORD dizem pra imagem do MySQL "cria esse banco, cria esse usuário com essa senha, define essa senha de root". Tudo na primeira inicialização.
Essa é a parte mais importante do card. A linha:
volumes:
- ./:/var/www/html
Diz: "monta a pasta atual do host (./, que é onde o yml está = C:\src\PROJETOS\WORDPRESS) no caminho /var/www/html dentro do container". E /var/www/html é justamente onde o Apache do container procura os arquivos do site.
O efeito é um espelho bidirecional:
| O que acontece | Resultado |
|---|---|
Você edita index.php no Windows | Container vê na hora — refresh no browser já mostra a mudança |
Container cria wp-config.php na instalação | Arquivo aparece em C:\src\PROJETOS\WORDPRESS\ |
Você adiciona um plugin (sobe um .zip pelo admin) | Arquivos do plugin aparecem em wp-content/plugins/ no Windows |
| Você apaga uma pasta no Windows | Some do container imediatamente |
O Docker não copia os arquivos. É um ponto de montagem, igual quando você espeta um pendrive — a pasta passa a aparecer "como se" estivesse lá dentro. Por isso é leve e instantâneo.
Bind mount é perfeito pra desenvolvimento: o código vive no seu Windows (versionado no git, editado no VS Code), e o container só "empresta" a pasta pra rodar Apache + PHP em cima dela.
Olhando agora o serviço db:
volumes:
- db_data:/var/lib/mysql
Parece igual, mas tem uma diferença crítica: não tem ./ no começo. db_data é um nome solto. Esse é um named volume — uma pasta interna gerenciada pelo Docker, que não fica visível na sua árvore do Windows.
Por isso o arquivo termina com a declaração:
volumes:
db_data:
Que diz pro Docker: "cria e gerencia um volume chamado db_data pra mim". Onde fica fisicamente? Numa pasta interna do Docker dentro do WSL. Você não precisa saber o caminho — quem manda nele é o Docker.
Por que pro banco a gente usa esse esquema e não bind mount?
Bind mount (./:/var/www/html) | Named volume (db_data:/var/lib/mysql) | |
|---|---|---|
| Onde os dados ficam | Na sua pasta do Windows | Numa área interna do Docker |
| Você consegue ver/editar? | Sim, é uma pasta normal | Não diretamente |
| Versionado no git? | Pode ser (e geralmente é) | Não |
| Performance | Mais lenta (cruza host ↔ container) | Nativa do Docker, rápida |
| Quando usar | Código fonte que você está editando | Dados de banco, cache, estado interno |
Com o yml pronto, são 4 comandos que cobrem 95% do uso:
# Sobe os 2 containers em background
docker compose up -d
# Acompanha logs de todos os serviços em tempo real
docker compose logs -f
# Para e remove os containers (preserva os volumes)
docker compose down
# Para, remove containers E APAGA os volumes — perde o banco
docker compose down -v
Diferença crucial entre down e down -v:
docker compose down — derruba os containers, mas o volume db_data continua intacto. Quando você der up de novo, o banco volta com todos os dados.docker compose down -v — derruba e apaga o volume. Quando você der up de novo, o banco volta vazio, e a tela de instalação do WordPress aparece de novo.O -v é útil quando você quer "começar do zero" pra testar a instalação do zero, mas é destrutivo — preserva apenas a pasta do código (que está no bind mount, fora do alcance do -v).
Depois desse exercício, o que vale guardar é:
ports abre uma janela entre o host e o container. Sem isso, o container fica fechado.environment configura o container pelo lado de fora, sem entrar lá dentro.down preserva volumes; down -v apaga.Com isso na cabeça, dá pra ler qualquer docker-compose.yml de projeto open source e entender o que cada bloco faz — independente do stack (PHP, Node, Python, Java).