Docker: Introdução ao Docker Compose
Última atualização: 2026-08-26
5 comandos docker run reduzidos a 1 docker compose up — o Compose transforma a implantação multi-contêiner de operações manuais para configuração declarativa.
1. O Que Você Vai Aprender
- Estrutura e Sintaxe do docker-compose.yml
- Definição de Serviço e Controle de Dependência
- Gerenciamento Declarativo de Volumes e Redes
- Estratégias de Gerenciamento de Variáveis de Ambiente
- Comandos Comuns do Docker Compose
2. Uma História Real de uma Pessoa Desenvolvedora
(1) Ponto de Dor: Ter que executar 5 comandos docker run toda vez que depuro
Toda vez que Alice depura, ela precisa digitar manualmente cinco comandos docker run para iniciar os quatro contêineres — Web, DB, Cache, Queue e Worker — o que envolve muitos parâmetros, exige a ordem correta e facilita erros de digitação nas variáveis de ambiente. Uma vez, ela esqueceu de incluir --network app-net e passou uma hora solucionando por que o contêiner Web não conseguia se conectar ao banco de dados.
(2) Soluções para Configuração Declarativa no Docker Compose
Bob escreveu um arquivo docker-compose.yml, então a partir de agora Alice só precisa executar docker compose up -d.
# docker-compose.yml - Um arquivo define tudo
services:
web:
image: nginx:alpine
ports: ["8080:80"]
depends_on:
- api
api:
build: .
environment:
- DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
db:
image: postgres:15-alpine
environment:
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=myapp
volumes:
- pg-data:/var/lib/postgresql/data
volumes:
pg-data:
networks:
default:
name: app-net
(3) Benefício: 5 comandos → 1 comando
A implantação foi reduzida de 5 comandos mais configuração manual para apenas 1 docker compose up -d. Pessoas recém-chegadas podem ter todo o projeto em execução em 5 minutos.
3. Estrutura do docker-compose.yml
(1) Os Três Campos Principais
# Estrutura do docker-compose.yml
services: # Definições de contêiner (obrigatório)
web:
image: nginx:alpine
volumes: # Declarações de volumes nomeados (opcional)
pg-data:
networks: # Declarações de redes personalizadas (opcional)
app-net:
(2) Comparação entre docker run e docker compose
| Dimensão | docker run | docker compose |
|---|---|---|
| Método de Definição | Argumentos de linha de comando | Arquivo YAML |
| Reprodutibilidade | Baixa (depende da memória da pessoa operadora) | Alta (arquivos podem ser commitados no Git) |
| Múltiplos contêineres | Múltiplos comandos | Um arquivo |
| Rede/Volume | Criação Manual | Gerenciamento Declarativo Automático |
| Variáveis de ambiente | Múltiplos argumentos -e | env_file ou bloco environment |
| Controle de Versão | ❌ | ✅ YAML oferece suporte a git diff |
4. Explicação Detalhada da Configuração de Serviços
(1) Campos Comuns de Serviço
| Campo | Propósito | Exemplo |
|---|---|---|
image |
Usar uma imagem existente | image: nginx:alpine |
build |
Construir a partir do Dockerfile | build: . ou build: { context: ., dockerfile: Dockerfile.prod } |
ports |
Mapeamento de porta | ports: ["8080:80"] |
environment |
Variáveis de Ambiente | environment: { POSTGRES_PASSWORD: secret } |
env_file |
Carregar variáveis de um arquivo | env_file: .env |
volumes |
Montar volume | volumes: [pg-data:/var/lib/postgresql/data] |
depends_on |
Dependências de Inicialização | depends_on: [db] |
restart |
Política de Reinicialização | restart: unless-stopped |
networks |
Rede Especificada | networks: [app-net] |
healthcheck |
Verificação de Saúde | healthcheck: { test: ["CMD", "curl", "-f", "http://localhost/"] } |
▶ Exemplo: Escrevendo o Arquivo Compose Mais Simples (Dificuldade: ⭐)
# docker-compose.yml mínimo
services:
web:
image: nginx:alpine
ports:
- "8080:80"
# Iniciar com compose
docker compose up -d
# Verificar
docker compose ps
5. Controle de Dependência: depends_on
(1) Três Estratégias de Espera
| Estratégia | Sintaxe | Aguardar Até | Descrição |
|---|---|---|---|
| started (padrão) | depends_on: [db] |
Contêiner iniciado | A prontidão do serviço não é garantida |
| healthy | depends_on: { db: { condition: service_healthy } } |
Verificação de saúde aprovada | ✅ Recomendado para uso em produção |
| completed | depends_on: { init: { condition: service_completed_successfully } } |
Contêiner encerrado com sucesso | Tarefa de inicialização |
▶ Exemplo: Controle de Dependência Usando depends_on e healthcheck (Dificuldade: ⭐⭐)
services:
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
api:
build: .
environment:
DATABASE_URL: postgresql://postgres:secret@db:5432/myapp
depends_on:
db:
condition: service_healthy
volumes:
pg-data:
depends_on: [db] (padrão) apenas aguarda o contêiner DB iniciar; não aguarda o PostgreSQL estar pronto. A API pode tentar se conectar antes que o DB esteja pronto e falhar. condition: service_healthy garante que a API não inicie até que o PostgreSQL esteja realmente pronto.
6. Declarações de Volumes e Redes
▶ Exemplo: Declarando Volumes e Redes (Dificuldade: ⭐⭐)
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./src:/usr/share/nginx/html:ro # Bind mount (somente leitura)
- nginx-cache:/var/cache/nginx # Volume nomeado
networks:
- frontend
- backend
api:
build: .
networks:
- backend
- database
db:
image: postgres:15-alpine
volumes:
- pg-data:/var/lib/postgresql/data
networks:
- database
volumes:
pg-data:
nginx-cache:
networks:
frontend:
backend:
database:
internal: true # Sem acesso externo
7. Gerenciamento de Variáveis de Ambiente
(1) Comparação dos Três Métodos
| Método | Sintaxe | Casos de Uso |
|---|---|---|
| Bloco environment | environment: { KEY: VALUE } |
Um pequeno número de variáveis fixas |
| env_file | env_file: .env |
Múltiplas Variáveis/Informações Sensíveis |
| Variáveis de Shell | environment: { KEY: ${VAR} } |
Configuração Dinâmica |
▶ Exemplo: env_file e substituição de variáveis (Dificuldade: ⭐⭐)
# docker-compose.yml com substituição de variáveis
services:
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD:-defaultsecret}
POSTGRES_DB: ${DB_NAME:-myapp}
env_file:
- .env.db
api:
build: .
environment:
DATABASE_URL: postgresql://postgres:${DB_PASSWORD:-defaultsecret}@db:5432/${DB_NAME:-myapp}
# .env.db
POSTGRES_USER=appuser
POSTGRES_PASSWORD=secret123
${VAR:-default}: Se VAR não estiver definida, use o valor padrão. Dessa forma, o arquivo compose tem valores padrão, que são sobrescritos pelo arquivo .env no ambiente de produção.
8. Comandos Comuns do Docker Compose
| Comando | Função | Exemplo |
|---|---|---|
docker compose up -d |
Iniciar todos os serviços (em segundo plano) | docker compose up -d |
docker compose down |
Parar e excluir todos os contêineres/redes | docker compose down |
docker compose down -v |
Excluir volumes simultaneamente | docker compose down -v |
docker compose ps |
Visualizar Status dos Serviços | docker compose ps |
docker compose logs |
Visualizar Logs | docker compose logs -f api |
docker compose exec |
Entrar no Contêiner | docker compose exec api bash |
docker compose build |
Reconstruir Imagem | docker compose build api |
docker compose pull |
Obter a imagem mais recente | docker compose pull |
docker compose config |
Verificar e exibir a configuração mesclada | docker compose config |
▶ Exemplo: Iniciar com docker compose up -d (Dificuldade: ⭐)
# Iniciar todos os serviços em modo desanexado
docker compose up -d
# Acompanhar logs de todos os serviços
docker compose logs -f
# Acompanhar logs de um serviço específico
docker compose logs -f api
▶ Exemplo: Entrando em um contêiner usando docker compose exec (Dificuldade: ⭐)
# Abrir shell no contêiner do serviço api
docker compose exec api bash
# Executar um comando único
docker compose exec db psql -U postgres -d myapp
▶ Exemplo: Limpeza com docker compose down (Dificuldade: ⭐)
# Parar e remover contêineres + redes
docker compose down
# Também remover volumes nomeados (ATENÇÃO: exclui dados)
docker compose down -v
# Também remover imagens
docker compose down --rmi all
9. Exemplo Completo: WordPress + MySQL
# ============================================
# docker-compose.yml: WordPress + MySQL
# Recursos: volumes, redes, depends_on, healthcheck
# ============================================
services:
wordpress:
image: wordpress:6.4-php8.2-apache
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD:-wppass123}
WORDPRESS_DB_NAME: wordpress
volumes:
- wp-content:/var/www/html/wp-content
depends_on:
mysql:
condition: service_healthy
restart: unless-stopped
networks:
- wp-net
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-rootsecret}
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: ${DB_PASSWORD:-wppass123}
volumes:
- mysql-data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- wp-net
volumes:
mysql-data:
wp-content:
networks:
wp-net:
# Implantar
docker compose up -d
# Verificar
docker compose ps
docker compose logs -f wordpress
# Acessar WordPress
# Abra http://localhost:8080 no navegador
# Limpar (mantém dados)
docker compose down
# Limpar tudo (exclui dados)
docker compose down -v
❓ Perguntas Frequentes
P: Qual versão devo usar para
docker-compose.yml? R: O novo Docker Compose V2 não exige mais o campoversion. Você pode começar a escrever diretamente a partir deservices:. Se você vir"version: "3.8"em tutoriais antigos, pode excluí-lo — o V2 o ignora.
P:
depends_ongarante que o serviço está pronto? R: Por padrão,depends_on: [db]garante apenas que o contêiner db inicie; não garante que o PostgreSQL está pronto. Você deve adicionarcondition: service_healthypara aguardar até que a verificação de saúde seja aprovada. Esta é a armadilha mais comum para iniciantes no Compose — o serviço inicia, mas a conexão falha porque a dependência não está pronta.
P: Como as variáveis de ambiente são gerenciadas nos arquivos Compose? R: Gerenciamento em três camadas: ① O bloco
environmentnodocker-compose.yml(valores padrão não sensíveis); ② O arquivo.env(valores específicos do ambiente, não commitados no Git); ③ A sintaxe${VAR:-default}(como fallback para valores padrão). Não inclua senhas sensíveis no YAML; use um arquivo.env+ .gitignore.
P:
docker compose downexclui volumes de dados? R: Por padrão, não.docker compose downApenas contêineres e redes são excluídos; Volumes Nomeados são retidos. Você deve adicionar-vpara excluir os volumes. Não usedown -vem ambientes de produção; use apenasdown.
P: Qual é o propósito do nome do projeto Compose? R: O nome do projeto isola os recursos de diferentes aplicações Compose. Por padrão, usa o nome do diretório atual.
docker compose -p myproject upVocê pode personalizar o nome do projeto. Vários projetos Compose podem ser executados na mesma máquina sem interferir uns nos outros.
📖 Resumo
- docker-compose.yml: Substitui múltiplos comandos
docker runpor YAML declarativo - Os três campos principais: services (definições de contêiner), volumes (volumes persistentes) e networks (redes)
depends_on+condition: service_healthyGarante que as dependências estejam realmente prontas- Variáveis de ambiente: Gerenciamento de três camadas usando o bloco
environment,env_filee${VAR:-default} docker compose up -dInicialização com um clique,docker compose downLimpeza com um cliquedocker compose configValida a sintaxe dos arquivos de configuração para evitar descobrir erros em tempo de execução
📝 Exercícios
- Exercício Básico (Dificuldade: ⭐): Escreva um arquivo
docker-compose.ymlpara a stack LEMP da Fase 1 (Nginx+PHP+MySQL) e inicie-o usandodocker compose up -d. - Exercício Avançado (Dificuldade: ⭐⭐): Adicione
depends_onehealthcheckao arquivocomposepara garantir que o PHP-FPM inicie somente após o MySQL estar pronto. - Desafio (Dificuldade: ⭐⭐⭐): Use
docker compose logspara solucionar um serviço que falhou ao iniciar, analise os logs para identificar a causa raiz e corrija o problema.