Aprenda / Infraestrutura — Docker

IntermediárioAula 14 de 1616 min0% da trilha

Compose avançado: profiles e overrides

Nem todo serviço precisa subir sempre, e dev/produção não deviam compartilhar o mesmo arquivo sem ajuste nenhum.

Até aqui, um único docker-compose.yml serviu tanto pra rodar localmente quanto (com variável de ambiente trocada) pra produção. Isso funciona pra projetos simples, mas dois problemas aparecem rápido: você quer coisas em dev que não fazem sentido em produção (bind mount de código, porta de debug), e às vezes só quer subir parte dos serviços, não todos. O Compose tem mecanismos prontos pra isso.

docker-compose.override.yml — o Compose já espera por ele

Se existir um arquivo chamado exatamente docker-compose.override.yml na mesma pasta do docker-compose.yml, o Compose mescla os dois automaticamente ao rodar docker compose up — sem precisar passar -f nenhum. É o lugar natural pra ajustes só de desenvolvimento local, mantendo o arquivo principal mais "neutro".

docker-compose.yml (base, comum a todo ambiente)
services:
  api:
    build: .
    environment:
      DATABASE_URL: postgres://postgres:postgres@db:5432/app
  db:
    image: postgres:16-alpine
docker-compose.override.yml (só dev, mesclado automaticamente)
services:
  api:
    volumes:
      - .:/app             # bind mount pra hot-reload em dev
    ports:
      - "9229:9229"        # porta de debug do Node, só faz sentido localmente

Múltiplos -f — combinando arquivos explicitamente

Pra produção, você não quer o override de dev, mas quer um arquivo próprio com ajustes de produção. Nesse caso, ignore o mecanismo automático e escolha os arquivos na mão, na ordem que fizer sentido — o Compose aplica um por cima do outro, na ordem em que aparecem:

terminal — produção
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Como o override automático só é aplicado quando você não passa -f, usar -f explicitamente (como acima) já ignora o docker-compose.override.yml por padrão — é assim que dev e produção deixam de compartilhar ajustes que só fazem sentido num dos dois lados.

profiles — subir só parte dos serviços

Serviços auxiliares (uma interface de administração de banco, uma ferramenta de debug) nem sempre precisam subir junto com o resto. Marcando um serviço com profiles, ele só sobe quando esse profile é ativado explicitamente — por padrão, fica de fora.

docker-compose.yml (trecho)
services:
  api:
    build: .
    # sem "profiles" — sobe sempre

  adminer:
    image: adminer
    ports:
      - "8081:8080"
    profiles: ["debug"]   # só sobe se o profile "debug" for ativado
terminal
docker compose up -d              # sobe só "api" (e "db", se não tiver profile)
docker compose --profile debug up -d   # sobe "api", "db" E "adminer"

Variáveis por ambiente: dev vs prod no mesmo projeto

docker-compose.prod.yml
services:
  api:
    restart: unless-stopped
    env_file: .env.production
    # sem bind mount, sem porta de debug — só o necessário pra rodar a imagem já buildada

A combinação docker-compose.yml (base) + docker-compose.override.yml (dev, automático) ou + docker-compose.prod.yml (produção, explícito via -f) evita duplicar o arquivo inteiro pra cada ambiente — só o que muda de fato fica declarado separadamente.

Exercício

Um projeto tem docker-compose.yml com os serviços api e db, e precisa de um serviço mailhog (captura de e-mail pra teste) que só deveria subir em desenvolvimento, nunca em produção. Onde declarar mailhog, e como isso evita que ele suba sem querer em produção?

Quiz rápido

O que o Compose faz automaticamente quando existe um arquivo docker-compose.override.yml na mesma pasta?
Pra que serve a chave profiles num serviço do compose?