Docker — Na prática

0:00 / 0:00

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.

O cenário

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:

Instalar 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.

A receita: docker-compose.yml

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.

Os dois serviços

Olhando o bloco services: de cima:

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.

Ports: a única janela pro mundo

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.

Environment: configurando sem editar arquivo

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.

Bind mount: espelhando a pasta do Windows

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 aconteceResultado
Você edita index.php no WindowsContainer vê na hora — refresh no browser já mostra a mudança
Container cria wp-config.php na instalaçãoArquivo 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 WindowsSome 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.

Named volume: o oposto do bind mount

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 vs named volume — a tabela

Bind mount (./:/var/www/html)Named volume (db_data:/var/lib/mysql)
Onde os dados ficamNa sua pasta do WindowsNuma área interna do Docker
Você consegue ver/editar?Sim, é uma pasta normalNão diretamente
Versionado no git?Pode ser (e geralmente é)Não
PerformanceMais lenta (cruza host ↔ container)Nativa do Docker, rápida
Quando usarCódigo fonte que você está editandoDados de banco, cache, estado interno

Comandos do dia a dia

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:

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).

Resumo: o modelo mental

Depois desse exercício, o que vale guardar é:

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).