Docker Compose em 2026: Aplicações Multi-Container, Redes e Perguntas de Entrevista DevOps

Guia completo sobre Docker Compose em 2026 cobrindo aplicações multi-container, configuração avançada de redes e perguntas frequentes em entrevistas DevOps.

Docker Compose Multi-Container Tutorial 2026

Docker Compose permanece como a ferramenta de referência para definir e executar aplicações Docker multi-container em 2026. Seja orquestrando um stack de desenvolvimento local ou se preparando para uma entrevista DevOps, o domínio das redes Compose, das dependências de serviços e dos padrões de produção diferencia engenheiros júnior de profissionais sênior.

Ponto Chave

Docker Compose utiliza um formato YAML declarativo para definir serviços, redes e volumes em um único arquivo. Executar docker compose up inicia toda a stack da aplicação com redes isoladas e armazenamento persistente.

Entendendo a Arquitetura do Docker Compose

Docker Compose opera sob um princípio simples: definir os serviços da aplicação em um arquivo compose.yaml (a convenção de nomenclatura moderna que substitui docker-compose.yml), e o Compose cuida da criação dos containers, das redes e do gerenciamento do ciclo de vida.

A especificação do Docker Compose define três conceitos fundamentais:

  • Serviços: Configurações de containers incluindo imagem, contexto de build, variáveis de ambiente e limites de recursos
  • Redes: Canais de comunicação isolados entre serviços
  • Volumes: Armazenamento de dados persistente que sobrevive às reinicializações dos containers
yaml
# compose.yaml
services:
  api:
    build: ./api
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://db:5432/app
    depends_on:
      db:
        condition: service_healthy
    networks:
      - backend

  db:
    image: postgres:16
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=app
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - backend

networks:
  backend:
    driver: bridge

volumes:
  postgres_data:

secrets:
  db_password:
    file: ./secrets/db_password.txt

Essa configuração demonstra vários padrões prontos para produção: health checks para ordenação de dependências, secrets do Docker para dados sensíveis, volumes nomeados para persistência e definições de rede explícitas.

Redes Docker Compose em Profundidade

Por padrão, o Compose cria uma única rede para a aplicação. Todos os serviços entram nessa rede e podem alcançar uns aos outros usando o nome do serviço como hostname. Entender esse modelo de rede é fundamental para uma migração para Kubernetes posterior.

yaml
# compose.yaml
services:
  frontend:
    build: ./frontend
    ports:
      - "80:80"
    networks:
      - frontend-net
      - backend-net

  api:
    build: ./api
    networks:
      - backend-net

  cache:
    image: redis:7-alpine
    networks:
      - backend-net

  db:
    image: postgres:16
    networks:
      - backend-net

networks:
  frontend-net:
    driver: bridge
  backend-net:
    driver: bridge
    internal: true

A flag internal: true impede que a rede backend acesse a Internet externa. O serviço frontend conecta ambas as redes, atuando como único ponto de entrada. Essa segmentação de rede reflete as práticas de segurança em produção.

Resolução DNS

O servidor DNS embutido do Docker resolve automaticamente os nomes de serviço. O serviço api alcança o banco de dados em db:5432 sem nenhuma configuração manual de IP.

Builds Multi-Estágio com Compose

As imagens de produção devem ser mínimas. Builds multi-estágio combinados com perfis do Compose permitem diferentes configurações para desenvolvimento e produção.

dockerfile
# api/Dockerfile
# Estágio 1: Build
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Estágio 2: Produção
FROM node:22-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]

# Estágio 3: Desenvolvimento
FROM node:22-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
USER node
CMD ["npm", "run", "dev"]
yaml
# compose.yaml
services:
  api:
    build:
      context: ./api
      target: ${BUILD_TARGET:-production}
    volumes:
      - ${API_VOLUMES:-./api/dist:/app/dist:ro}
    profiles:
      - ${COMPOSE_PROFILES:-prod}

Executar BUILD_TARGET=development COMPOSE_PROFILES=dev docker compose up inicia a configuração de desenvolvimento com hot reload.

Dependências de Serviços e Health Checks

A diretiva depends_on controla a ordem de inicialização, mas os containers iniciarem não significa que os serviços estão prontos. Os health checks resolvem esse problema de timing—um padrão frequentemente perguntado em entrevistas DevOps.

yaml
# compose.yaml
services:
  api:
    build: ./api
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
      migrations:
        condition: service_completed_successfully

  migrations:
    build: ./api
    command: npm run migrate
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s

  cache:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 3

Existem três condições de dependência:

  • service_started: Padrão, o container iniciou
  • service_healthy: O health check passou
  • service_completed_successfully: O container terminou com código 0 (para containers de inicialização)

Pronto para mandar bem nas entrevistas de DevOps?

Pratique com nossos simuladores interativos, flashcards e testes tecnicos.

Docker Compose para Desenvolvimento Local

Os ambientes de desenvolvimento se beneficiam de bind mounts, overrides de ambiente e ferramentas de depuração. O arquivo compose.override.yaml é automaticamente mesclado com compose.yaml.

yaml
# compose.yaml (configuração base)
services:
  api:
    build: ./api
    environment:
      - NODE_ENV=production

  db:
    image: postgres:16
yaml
# compose.override.yaml (overrides de desenvolvimento)
services:
  api:
    build:
      target: development
    volumes:
      - ./api:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DEBUG=app:*
    ports:
      - "9229:9229"

  db:
    ports:
      - "5432:5432"

O volume anônimo /app/node_modules impede que o node_modules do host sobrescreva as dependências instaladas do container.

Padrões de Deploy em Produção

Docker Compose funciona para deploys de produção em um único host. Para orquestração multi-host, Kubernetes com Helm oferece melhor escalabilidade, mas o Compose permanece viável para aplicações menores.

yaml
# compose.prod.yaml
services:
  api:
    image: registry.example.com/api:${VERSION:-latest}
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: "0.5"
          memory: 512M
        reservations:
          cpus: "0.25"
          memory: 256M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
    depends_on:
      - api

A chave deploy configura limites de recursos, quantidade de réplicas e políticas de reinicialização. Executar docker compose -f compose.prod.yaml up -d inicia a stack de produção em modo desanexado.

Variáveis de Ambiente e Gerenciamento de Secrets

A configuração sensível requer tratamento apropriado. Docker Compose suporta múltiplas abordagens, desde arquivos .env até secrets do Docker.

bash
# .env
POSTGRES_PASSWORD=dev_password_only
API_SECRET_KEY=local_dev_key
yaml
# compose.yaml
services:
  api:
    environment:
      - API_SECRET_KEY  # Herda do shell ou .env
      - DATABASE_URL=postgres://user:${POSTGRES_PASSWORD}@db:5432/app
    env_file:
      - ./config/api.env

Para produção, os secrets do Docker fornecem melhor segurança ao montar dados sensíveis como arquivos em vez de variáveis de ambiente:

yaml
# compose.prod.yaml
services:
  api:
    secrets:
      - api_key
      - db_password
    environment:
      - API_KEY_FILE=/run/secrets/api_key

secrets:
  api_key:
    external: true
  db_password:
    file: ./secrets/db_password.txt
Nota de Segurança

Nunca faça commit de arquivos .env contendo secrets de produção no controle de versão. Use soluções externas de gerenciamento de secrets como HashiCorp Vault ou soluções de provedores cloud para deploys de produção.

Perguntas Comuns de Entrevista DevOps sobre Docker Compose

Os entrevistadores testam o entendimento dos conceitos do Compose através de cenários práticos. Essas perguntas aparecem frequentemente em entrevistas de DevOps e engenharia de plataforma.

P: Como os containers em uma rede Compose se comunicam?

O Docker cria uma rede bridge dedicada para cada projeto Compose. Os serviços se comunicam usando seus nomes de serviço como hostnames. O servidor DNS embutido resolve esses nomes para endereços IP dos containers. O tráfego externo alcança os serviços apenas através de portas explicitamente publicadas.

P: O que acontece quando se executa docker compose up com containers existentes?

O Compose compara a configuração atual com os containers em execução. Serviços sem alterações continuam executando. Serviços modificados são recriados com as novas configurações. Novos serviços iniciam do zero. Serviços removidos são parados e deletados.

P: Como lidar com migrações de banco de dados no Compose?

Existem dois padrões. Primeiro, usar um container de inicialização com dependência service_completed_successfully:

yaml
services:
  migrate:
    image: api:latest
    command: npm run migrate
    depends_on:
      db:
        condition: service_healthy

  api:
    depends_on:
      migrate:
        condition: service_completed_successfully

Segundo, incluir a lógica de migração no script de inicialização da aplicação, verificando e aplicando migrações pendentes antes de aceitar tráfego.

P: Qual a diferença entre volumes e bind mounts?

Volumes nomeados são gerenciados pelo Docker, armazenados em /var/lib/docker/volumes, e portáveis entre hosts. Bind mounts mapeiam diretórios do host diretamente nos containers, úteis para desenvolvimento mas dependentes do ambiente. Volumes suportam drivers para armazenamento remoto como NFS ou armazenamento em blocos na nuvem.

P: Qual a diferença entre docker-compose e docker compose?

O docker-compose com hífen era a ferramenta standalone V1 baseada em Python, agora depreciada. O docker compose com espaço é a implementação V2 baseada em Go integrada ao CLI do Docker. V2 é mais rápido, suporta completamente a Especificação do Compose e recebe desenvolvimento ativo.

Depuração de Aplicações Compose

A resolução de problemas em aplicações containerizadas requer técnicas específicas. Esses comandos revelam o que está acontecendo dentro da stack do Compose:

bash
# Ver logs de todos os serviços
docker compose logs -f

# Logs de um serviço específico com timestamps
docker compose logs -f --timestamps api

# Executar comando em container em execução
docker compose exec api sh

# Executar comando único (inicia novo container)
docker compose run --rm api npm test

# Ver uso de recursos
docker compose top
docker stats

# Inspecionar configuração de rede
docker network inspect project_backend

# Validar arquivo compose
docker compose config

O comando docker compose config mescla todos os arquivos compose e mostra a configuração final—inestimável para depurar problemas de interpolação de variáveis.

Conclusão

  • Docker Compose define aplicações multi-container em um único arquivo YAML com serviços, redes e volumes
  • Os serviços se comunicam via DNS usando nomes de serviço como hostnames dentro da rede bridge padrão
  • Health checks com condições service_healthy garantem ordenamento de inicialização correto
  • Use compose.override.yaml para configurações específicas de desenvolvimento como bind mounts e portas de depuração
  • Deploys de produção se beneficiam de limites de recursos, políticas de reinicialização e secrets do Docker para dados sensíveis
  • O CLI docker compose (V2) substitui o depreciado docker-compose (V1) com melhor performance e funcionalidades

Comece a praticar!

Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.

Tags

#docker
#docker-compose
#devops
#containers
#networking

Compartilhar

Artigos relacionados