Docker Compose para Desenvolvimento Local: Um Guia Prático para Otimizar seu Workflow
Aprenda a configurar o Docker Compose para criar ambientes de desenvolvimento local consistentes. Elimine o 'na minha máquina funciona' com este guia prático focado em stacks multi-serviço.
Configurar um ambiente de desenvolvimento local do zero costuma ser uma das tarefas mais frustrantes para um time de tecnologia. Instalar versões específicas de bancos de dados, configurar serviços de mensageria, alinhar variáveis de ambiente e garantir que todos os desenvolvedores rodem exatamente a mesma pilha de software consome um tempo precioso. É nesse cenário que o Docker Compose se consolida como uma ferramenta indispensável, eliminando de vez o clássico fantasma do “na minha máquina funciona”.
Neste guia prático, você aprenderá a estruturar um ambiente local multi-serviço consistente, reprodutível e declarativo, otimizando o tempo de inicialização do seu projeto e garantindo que qualquer novo membro do time consiga rodar a aplicação com um único comando.
O que é o Docker Compose e por que ele é indispensável no desenvolvimento local
O Docker Compose é uma ferramenta desenvolvida para definir e rodar aplicações multi-contêiner no Docker. Em vez de gerenciar cada contêiner individualmente, você utiliza um único arquivo de configuração em formato YAML para especificar todos os serviços, redes e volumes que a sua aplicação necessita.
No dia a dia de um time de desenvolvimento, a consistência é fundamental. Sem uma ferramenta de orquestração local, é comum que desenvolvedores utilizem versões ligeiramente diferentes do PostgreSQL, Redis ou Node.js em suas máquinas físicas. Essas discrepâncias geram bugs difíceis de rastrear e atrasam o processo de onboarding.
Ao adotar o Docker Compose, todo o ambiente é documentado como código. Se você quer entender melhor os conceitos fundamentais de isolamento antes de avançar, vale a pena ler sobre como usar o Docker Para Facilitar o Desenvolvimento e compreender a base de O que são Containers e Orquestração.
Docker CLI vs. Docker Compose: A transição para a orquestração declarativa
Quando começamos a trabalhar com Docker, é natural utilizarmos a interface de linha de comando padrão (Docker CLI). No entanto, para rodar uma aplicação web simples conectada a um banco de dados, o fluxo imperativo exige comandos longos e complexos no terminal:
docker network create minha-rede
docker run --name meu-postgres --network minha-rede -e POSTGRES_PASSWORD=senha_secreta -d postgres:15-alpine
docker run --name minha-app --network minha-rede -p 3000:3000 -e DATABASE_URL=postgres://postgres:senha_secreta@meu-postgres:5432/postgres -d minha-imagem-web:latest
Esse modelo imperativo apresenta sérios problemas de escala:
- Dificuldade de compartilhamento: Cada desenvolvedor precisa copiar, colar e adaptar esses comandos.
- Manutenção complexa: Alterar uma variável de ambiente ou uma porta exige parar, remover e recriar os contêineres manualmente.
- Falta de versionamento: As configurações do ambiente local ficam perdidas no histórico do terminal de cada um.
Com o Docker Compose, fazemos a transição para a abordagem declarativa. Você define o estado desejado do seu ambiente em um arquivo de configuração e deixa que a ferramenta gerencie o ciclo de vida dos contêineres, redes e volumes necessários para atingir esse estado.
Anatomia de um arquivo compose.yml: Serviços, Redes e Volumes
O arquivo de configuração padrão do Docker Compose é o compose.yml (historicamente conhecido como docker-compose.yml). Sua estrutura é dividida em três pilares principais:
- Services (Serviços): Representam os contêineres que serão iniciados. Cada serviço define a imagem que será utilizada (ou o caminho para o
Dockerfilepara build local), portas expostas, variáveis de ambiente e dependências. - Volumes: Mecanismos para persistência e compartilhamento de dados. Por padrão, os dados dentro de um contêiner são efêmeros e desaparecem quando ele é removido. Os volumes garantem que os dados do seu banco de dados local sobrevivam a reinicializações.
- Networks (Redes): O Docker Compose cria automaticamente uma rede isolada para a sua stack. Todos os serviços definidos no mesmo arquivo conseguem se comunicar entre si utilizando apenas o nome do serviço como host (ex:
http://db:5432), sem a necessidade de expor portas sensíveis para a máquina hospedeira.
Guia Prático: Configurando uma Stack Multi-Serviço (Web App + PostgreSQL)
Abaixo, apresentamos um exemplo real de um arquivo compose.yml que integra uma aplicação web (Node.js/Python/Go) a um banco de dados PostgreSQL, aplicando as melhores práticas de isolamento e persistência.
services:
web:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
depends_on:
db:
condition: service_healthy
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_NAME}
ports:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 5s
timeout: 5s
retries: 5
volumes:
db-data:
Neste exemplo, o serviço web é construído localmente a partir do Dockerfile presente na raiz do projeto, enquanto o serviço db utiliza uma imagem oficial e leve do PostgreSQL baseada em Alpine Linux.
Persistência de dados e segurança: Volumes nomeados e arquivos .env
Para que o ambiente local seja prático, você não pode perder seus dados de teste toda vez que reiniciar o computador. No YAML acima, resolvemos isso declarando um volume nomeado:
volumes:
db-data:
E mapeando-o dentro do serviço de banco de dados:
volumes:
- db-data:/var/lib/postgresql/data
Isso direciona os arquivos físicos do PostgreSQL para uma área gerenciada pelo Docker na sua máquina hospedeira, garantindo a persistência.
Gerenciamento seguro com arquivos .env
Evite expor credenciais diretamente no arquivo compose.yml. O Docker Compose possui suporte nativo para arquivos .env. Crie um arquivo chamado .env na mesma pasta do seu compose.yml:
DB_USER=postgres_user
DB_PASSWORD=super_senha_local_123
DB_NAME=app_desenvolvimento
O Compose lerá essas variáveis automaticamente e substituirá as marcações ${DB_USER}, ${DB_PASSWORD} e ${DB_NAME} em tempo de execução. Lembre-se de adicionar o arquivo .env ao seu .gitignore e disponibilizar um .env.example com valores fictícios para o restante do time.
Controle de inicialização: depends_on e a importância de Health Checks
Um erro muito comum ao iniciar stacks multi-serviço é a aplicação web falhar ao tentar se conectar ao banco de dados porque o contêiner do banco ainda está inicializando seus processos internos.
Apenas declarar depends_on: [db] não resolve o problema, pois o Docker considera o contêiner “pronto” assim que o processo principal é iniciado, e não quando o banco de dados está de fato aceitando conexões.
Para solucionar isso de forma robusta, combinamos a diretiva depends_on com um Health Check (teste de saúde):
depends_on:
db:
condition: service_healthy
No serviço db, definimos o teste de saúde utilizando o utilitário pg_isready:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 5s
timeout: 5s
retries: 5
Agora, o Docker Compose aguardará até que o PostgreSQL passe com sucesso no teste de saúde antes de iniciar o contêiner da aplicação web, evitando falhas de conexão na inicialização.
Comandos essenciais do Docker Compose para o dia a dia
Para operar seu ambiente local com eficiência, você precisa dominar os comandos básicos do dia a dia. Certifique-se de estar no mesmo diretório do arquivo compose.yml ao executá-los:
docker compose up: Inicializa todos os serviços definidos. Use a flag-dpara rodar em segundo plano (detached mode).docker compose down: Para e remove todos os contêineres e redes criados pela stack. Para apagar também os volumes persistentes, adicione a flag-v.docker compose build: Reconstrói as imagens locais (útil após alterar dependências no seupackage.jsonourequirements.txt).docker compose logs -f: Exibe e acompanha os logs de todos os contêineres em tempo real. Você pode especificar um serviço (ex:docker compose logs -f web).docker compose ps: Lista o status de todos os contêineres gerenciados pela stack local.
Quando o Docker Compose não é suficiente? O caminho para a produção
Embora o Docker Compose seja a ferramenta perfeita para desenvolvimento local, testes automatizados em pipelines e prototipagem rápida, ele possui limitações claras. Ele não foi projetado para lidar com alta disponibilidade, escalonamento horizontal dinâmico entre múltiplas máquinas físicas, rolling updates complexos ou gerenciamento avançado de redes em produção.
Para cenários de produção robustos e em larga escala, ferramentas de orquestração de contêineres como Kubernetes ou Docker Swarm são as soluções adequadas. No entanto, o aprendizado adquirido ao estruturar seu ambiente local com o Compose serve como uma excelente base para essas tecnologias.
Se você deseja dar o próximo passo e automatizar a entrega da sua aplicação conteinerizada, confira nosso guia sobre Como implementar CI/CD com GitHub Actions e Docker de forma simples.
Perguntas Frequentes (FAQ)
Como faço para atualizar um contêiner após alterar o código da minha aplicação?
Você deve rodar o comando docker compose up --build para forçar o Docker Compose a reconstruir a imagem do serviço que sofreu alterações no código ou no Dockerfile antes de iniciar os contêineres.
Por que meus dados do banco de dados somem quando eu rodo ‘docker compose down’?
Isso acontece se você não configurou um volume persistente. Para manter os dados, você deve mapear um volume nomeado no seu compose.yml apontando para o diretório de dados do banco de dados (como /var/lib/postgresql/data no caso do Postgres).
Posso usar múltiplos arquivos .env para diferentes ambientes com o Docker Compose?
Sim. Por padrão, o Docker Compose lê o arquivo .env na raiz do projeto, mas você pode especificar arquivos de ambiente diferentes usando a flag --env-file no terminal ou a diretiva env_file dentro do compose.yml.
Sobre Marcos Costa
Desenvolvedor backend com foco em arquitetura de software, automação e produtos digitais.
Ver mais artigos