Conteúdo
Sintaxe completa do compose.yaml: tutorial de Docker Compose
O nível superior de compose.yaml tem quatro seções principais:
name: myapp # Nome do projeto (opcional, por padrão é o nome da pasta)
services: # Contêineres a executar
...
volumes: # Volumes nomeados
...
networks: # Rede personalizada (opcional; uma é criada automaticamente por padrão)
...
A seguir, explicamos as configurações mais usadas em services de acordo com sua finalidade. No final, executamos um exemplo completo.
image e build
Use uma imagem existente:
services:
redis:
image: redis:8-alpine
Construa a imagem a partir de um Dockerfile:
services:
app:
build: . # Use o Dockerfile da pasta atual
Quando precisar de mais opções:
services:
app:
build:
context: ./backend
dockerfile: Dockerfile.prod
target: prod # Etapa alvo do build em vários estágios
args:
APP_VERSION: "1.4.2"
image: myorg/app:1.4.2 # Nome da imagem após o build
Se você definir build e image, o Compose dará ao resultado do build o nome especificado em image. Depois, você poderá executar docker compose push.
ports: portas
ports:
- "8080:80" # Host:contêiner
- "127.0.0.1:5432:5432" # Disponível apenas localmente
- "9000-9002:9000-9002" # Intervalo
Coloque entre aspas. O YAML pode interpretar alguns formatos número:número como números na base 60, causando erros estranhos.
expose apenas documenta a finalidade; não expõe a porta externamente. Os serviços na mesma rede já podem se comunicar entre si.
volumes: montagens
services:
db:
image: postgres:18
volumes:
- pgdata:/var/lib/postgresql # Volume nomeado
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro # Bind mount (caminho relativo)
volumes:
pgdata:
-
Os caminhos que começam com
./ou../são Bind mounts relativos acompose.yaml. -
Um nome sem caminho indica um Volume nomeado. Você precisa declará-lo na seção
volumes:do nível superior. O nome real receberá o prefixo do projeto (por exemplo,shop_pgdata). -
Para usar um Volume criado fora do Compose:
volumes: pgdata: external: true
environment e env_file
environment:
NODE_ENV: production
DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/app
env_file:
- .env.app
Os valores de ${...} vêm do arquivo .env ou das variáveis de ambiente atuais. Consulte Variáveis de ambiente e arquivos .env.
depends_on e healthcheck: aguarde o banco de dados ficar realmente pronto
depends_on controla apenas a ordem de inicialização: garante que o contêiner db seja iniciado primeiro, mas não garante que o banco de dados já esteja pronto para aceitar conexões. O PostgreSQL leva alguns segundos para iniciar, e o aplicativo pode falhar por não conseguir se conectar. Com healthcheck e condition: service_healthy, o Compose aguarda a verificação de integridade ser aprovada antes de iniciar o aplicativo.
Exemplo prático (compose.yaml):
name: shop
services:
app:
image: postgres:18
command: ["psql", "-h", "db", "-U", "shop", "-c", "SELECT 'app connected' AS status;"]
environment:
PGPASSWORD: ${DB_PASSWORD}
depends_on:
db:
condition: service_healthy
db:
image: postgres:18
environment:
POSTGRES_USER: shop
POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD is required}
POSTGRES_DB: shop
volumes:
- pgdata:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -U shop -d shop"]
interval: 2s
timeout: 3s
retries: 20
adminer:
image: adminer
ports:
- "8081:8080"
profiles: [tools]
volumes:
pgdata:
O serviço app usa o cliente do PostgreSQL para simular um aplicativo que precisa se conectar ao banco de dados ao iniciar. Defina DB_PASSWORD=change-me no arquivo .env.
Inicie apenas o db e observe a mudança do estado de integridade:
$ docker compose up -d db
[+] up 3/3
✔ Network shop_default Created 0.0s
✔ Volume shop_pgdata Created 0.0s
✔ Container shop-db-1 Started 0.3s
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
shop-db-1 postgres:18 "docker-entrypoint.s…" db 1 second ago Up Less than a second (health: starting) 127.0.0.1:5432->5432/tcp
Após alguns segundos:
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
shop-db-1 postgres:18 "docker-entrypoint.s…" db 10 seconds ago Up 9 seconds (healthy) 127.0.0.1:5432->5432/tcp
O estado muda de health: starting para healthy. Depois de encerrar tudo, inicie o app do zero:
$ docker compose up app
[+] up 3/3
✔ Network shop_default Created 0.0s
✔ Container shop-db-1 Created 0.0s
✔ Container shop-app-1 Created 0.1s
Attaching to app-1
Container shop-db-1 Waiting
Container shop-db-1 Healthy
app-1 | status
app-1 | ---------------
app-1 | app connected
app-1 | (1 row)
app-1 |
app-1 exited with code 0
w Enable Watch d Detach
O Compose inicia primeiro o db, exibe Waiting e só inicia o app quando o estado passa a Healthy. Assim, a primeira tentativa de conexão do app é bem-sucedida (app connected). Sem condition: service_healthy, o app tentaria se conectar antes de o banco de dados estar pronto.
(A última linha, w Enable Watch d Detach, mostra os atalhos disponíveis quando o Compose está sendo executado em primeiro plano.)
A verificação de integridade usa
pg_isreadycom-h 127.0.0.1. Sem essa opção, o banco de dados seria considerado healthy durante a inicialização inicial, e o aplicativo acabaria falhando ao se conectar. Veja os testes em PostgreSQL. O MySQL também apresenta o mesmo problema; veja MySQL.
Valores disponíveis para condition:
| Valor | Significado |
|---|---|
service_started | O contêiner foi iniciado (padrão) |
service_healthy | A verificação de integridade foi aprovada |
service_completed_successfully | O serviço terminou a execução com código de saída 0; adequado para tarefas pontuais, como migrações de banco de dados |
Você também pode adicionar restart: true em depends_on. Quando db for reiniciado, app também será reiniciado.
restart
restart: unless-stopped
Valores disponíveis: no, always, on-failure, unless-stopped (veja o comportamento em Ciclo de vida do contêiner).
command e entrypoint
Substitua o CMD / ENTRYPOINT da imagem:
command: ["npm", "run", "dev"]
entrypoint: ["/app/docker-entrypoint.sh"]
networks
Por padrão, todos os serviços ficam na mesma rede nome_do_projeto_default. Para isolá-los, você pode criar redes personalizadas:
services:
web:
image: nginx:1.30-alpine
networks: [frontend]
app:
build: .
networks: [frontend, backend]
db:
image: postgres:18
networks: [backend]
networks:
frontend:
backend:
web pode se conectar a app, mas não a db.
profiles: inicialização seletiva de serviços
O serviço adminer do exemplo acima tem profiles: [tools]:
$ docker compose config --services
db
app
$ docker compose --profile tools config --services
db
app
adminer
Sem especificar um profile, adminer não será iniciado. Ele só será iniciado quando você adicionar --profile tools. Isso é útil para serviços que você inicia apenas quando precisa, como ferramentas de administração e servidores de e-mail para testes.
Limites de recursos e outras configurações comuns
services:
app:
image: myorg/app:1.4.2
container_name: app # Nome fixo do contêiner (não pode ser escalado depois)
user: "1000:1000"
working_dir: /app
mem_limit: 512m
cpus: 1.5
init: true # Equivale a docker run --init
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
extra_hosts:
- "host.docker.internal:host-gateway"
compose.override.yaml: configuração mesclada
O Compose mescla automaticamente compose.yaml e compose.override.yaml. A pasta do exemplo também contém este arquivo:
# compose.override.yaml
services:
db:
ports:
- "127.0.0.1:5432:5432"
Use docker compose config para ver a configuração final mesclada (observe o ports no final):
$ docker compose config db
name: shop
services:
db:
environment:
POSTGRES_DB: shop
POSTGRES_PASSWORD: change-me
POSTGRES_USER: shop
image: postgres:18
networks:
default: null
volumes:
- type: volume
source: pgdata
target: /var/lib/postgresql
volume: {}
healthcheck:
test:
- CMD-SHELL
- pg_isready -h 127.0.0.1 -U shop -d shop
timeout: 3s
interval: 2s
retries: 20
ports:
- mode: ingress
host_ip: 127.0.0.1
target: 5432
published: "5432"
protocol: tcp
networks:
default:
name: shop_default
volumes:
pgdata:
name: shop_pgdata
Ao especificar explicitamente apenas um arquivo com -f compose.yaml, o override não é mesclado e ports também desaparece:
$ docker compose -f compose.yaml config db
name: shop
services:
db:
environment:
POSTGRES_DB: shop
POSTGRES_PASSWORD: change-me
POSTGRES_USER: shop
image: postgres:18
networks:
default: null
volumes:
- type: volume
source: pgdata
target: /var/lib/postgresql
volume: {}
healthcheck:
test:
- CMD-SHELL
- pg_isready -h 127.0.0.1 -U shop -d shop
timeout: 3s
interval: 2s
retries: 20
networks:
default:
name: shop_default
volumes:
pgdata:
name: shop_pgdata
docker compose config também expande a forma abreviada para o formato completo (por exemplo, pgdata:/var/lib/postgresql vira type: volume, source e target) e substitui ${DB_PASSWORD}. Quando uma configuração parece não ter efeito, o primeiro passo é usar esse comando para confirmar o que o Compose realmente leu.
Uma divisão comum:
compose.yaml: configurações compartilhadas por todos os ambientes.compose.override.yaml: exclusivo para desenvolvimento (monta o código-fonte, abre portas para depuração) e aplicado automaticamente ao executardocker compose uplocalmente.compose.prod.yaml: para produção, especificado comdocker compose -f compose.yaml -f compose.prod.yaml up -d.
Resumo
imageusa uma imagem existente;buildconstrói uma imagem a partir de um Dockerfile.- Só
depends_on+condition: service_healthyespera até que o serviço esteja realmente pronto. profilespermite iniciar serviços como ferramentas administrativas somente quando necessário.compose.override.yamlé mesclado automaticamente. Usedocker compose configpara verificar a configuração final.
Exercícios
Exercício 1: Adicione restart: unless-stopped ao serviço db deste capítulo e limite a memória a 512 MB.
Resposta
db:
image: postgres:18
restart: unless-stopped
mem_limit: 512m
Depois da alteração, execute docker compose up -d para aplicá-la.
Exercício 2: adminer está configurado com profiles: [tools]. Como iniciá-lo junto?
Resposta
docker compose --profile tools up -d
Perguntas frequentes
Por que depends_on não espera o banco de dados ficar pronto?
Escrever apenas depends_on: [db] garante somente a ordem de inicialização. Para esperar até que o banco de dados aceite conexões, você precisa de healthcheck com condition: service_healthy. Veja como configurar a verificação de integridade neste capítulo e em [PostgreSQL](/pt/docker/postgresql/).
O que acontece se a indentação do YAML estiver errada?
docker compose config exibirá um erro, por exemplo, did not find expected key. Consulte [Mensagens de erro comuns](/pt/docker/errors/). Use apenas espaços, nunca Tab.
Ainda é necessário escrever version: '3.8'?
Não. A especificação do Compose não usa mais o campo version. As versões atuais o ignoram e exibem um aviso.
Atualizado 14 de outubro de 2026