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



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.

YAML
# 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

YAML
# 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: ⭐)

YAML
# docker-compose.yml mínimo
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
BASH
# 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: ⭐⭐)

YAML
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:
💡 Dica: 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: ⭐⭐)

YAML
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: ⭐⭐)

YAML
# 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}
BASH
# .env.db
POSTGRES_USER=appuser
POSTGRES_PASSWORD=secret123
📌 Ponto-chave: Sintaxe ${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: ⭐)

BASH
# 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: ⭐)

BASH
# 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: ⭐)

BASH
# 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

YAML
# ============================================
# 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:
BASH
# 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 campo version. Você pode começar a escrever diretamente a partir de services:. Se você vir "version: "3.8" em tutoriais antigos, pode excluí-lo — o V2 o ignora.

P: depends_on garante 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 adicionar condition: service_healthy para 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 environment no docker-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 down exclui volumes de dados? R: Por padrão, não. docker compose down Apenas contêineres e redes são excluídos; Volumes Nomeados são retidos. Você deve adicionar -v para excluir os volumes. Não use down -v em ambientes de produção; use apenas down.

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 up Você pode personalizar o nome do projeto. Vários projetos Compose podem ser executados na mesma máquina sem interferir uns nos outros.


📖 Resumo


📝 Exercícios

  1. Exercício Básico (Dificuldade: ⭐): Escreva um arquivo docker-compose.yml para a stack LEMP da Fase 1 (Nginx+PHP+MySQL) e inicie-o usando docker compose up -d.
  2. Exercício Avançado (Dificuldade: ⭐⭐): Adicione depends_on e healthcheck ao arquivo compose para garantir que o PHP-FPM inicie somente após o MySQL estar pronto.
  3. Desafio (Dificuldade: ⭐⭐⭐): Use docker compose logs para solucionar um serviço que falhou ao iniciar, analise os logs para identificar a causa raiz e corrija o problema.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%