Docker Compose: Orquestrar Múltiplos Containers do Zero com YAML
Docker Compose é a ferramenta oficial para definir e rodar aplicações multi-container. Em vez de executar 3 comandos docker run longos com opções difíceis de lembrar, você descreve toda a stack em um arquivo YAML e sobe tudo com docker compose up.
Instalação
# Docker Compose v2 já vem integrado ao Docker Engine (como plugin)
docker compose version # deve retornar v2.x
# Se não estiver disponível, instalar o plugin
sudo apt install docker-compose-plugin -y
# Versão standalone (legado, ainda funciona)
sudo apt install docker-compose -y # docker-compose (com hífen)
Estrutura do docker-compose.yml
version: "3.9"
services:
app:
build: . # usa o Dockerfile na raiz
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://user:senha@db:5432/meudb
depends_on:
db:
condition: service_healthy # espera o banco estar pronto
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: senha
POSTGRES_DB: meudb
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
pgdata: # volume nomeado, persiste entre restarts
Comandos Essenciais
# Subir todos os serviços em background
docker compose up -d
# Ver logs de todos (ou de um serviço específico)
docker compose logs -f
docker compose logs -f app
# Listar containers do projeto
docker compose ps
# Parar e remover containers (mantém volumes)
docker compose down
# Parar, remover containers E volumes
docker compose down -v
# Rebuildar imagem e recriar container
docker compose up -d --build app
# Rodar comando em container em execução
docker compose exec app bash
docker compose exec db psql -U user meudb
Variáveis de Ambiente com .env
Nunca coloque senhas direto no docker-compose.yml. Use um arquivo .env na mesma pasta (e adicione ao .gitignore):
# .env
POSTGRES_USER=user
POSTGRES_PASSWORD=senha_super_segura
POSTGRES_DB=meudb
# docker-compose.yml — referencia com ${VAR}
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
Volumes: Persistência de Dados
services:
app:
volumes:
# Volume nomeado (gerenciado pelo Docker)
- dados_app:/app/uploads
# Bind mount (pasta do host mapeada no container)
# Útil em desenvolvimento para hot-reload
- ./src:/app/src
# Arquivo único montado no container
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
volumes:
dados_app:
Bind mounts são ótimos para desenvolvimento — você edita o arquivo no host e o container vê a mudança imediatamente. Em produção, prefira volumes nomeados pois são gerenciados pelo Docker e mais fáceis de fazer backup.
Redes: Comunicação entre Serviços
Por padrão, todos os serviços num mesmo docker-compose.yml estão na mesma rede e podem se comunicar pelo nome do serviço como hostname. O serviço app acessa o banco em db:5432, não em localhost:5432.
# Redes customizadas (para isolamento)
networks:
frontend:
backend:
services:
nginx:
networks: [frontend, backend]
app:
networks: [backend]
db:
networks: [backend]
Exemplo Real: WordPress + MySQL + Nginx
version: "3.9"
services:
nginx:
image: nginx:alpine
ports: ["80:80"]
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- wordpress:/var/www/html
depends_on: [wordpress]
wordpress:
image: wordpress:php8.2-fpm
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: ${DB_USER}
WORDPRESS_DB_PASSWORD: ${DB_PASS}
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress:/var/www/html
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASS}
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
volumes:
- dbdata:/var/lib/mysql
volumes:
wordpress:
dbdata:
Docker Compose vs Kubernetes
Compose é para uma máquina; Kubernetes é para um cluster. Para projetos com 1–5 serviços em um servidor, Compose é a escolha certa — simples, sem curva de aprendizado de K8s, fácil de fazer backup e migrar. Use Kubernetes quando precisar de auto-escalonamento horizontal ou alta disponibilidade com múltiplos nodes.