🐳 Docker Compose - Orquestração de Containers
Conceitos, Configuração, MySQL, PostgreSQL e Desenvolvimento Local
1. O que é Docker Compose?
Docker Compose é uma ferramenta que permite definir e executar aplicações multi-container com Docker. Com um único arquivo YAML, você pode descrever todos os serviços, redes e volumes necessários para sua aplicação.
Em vez de executar múltiplos comandos `docker run`, você define tudo em um arquivo `docker-compose.yml` e inicia com um simples comando: `docker-compose up`.
Docker Compose é ideal para desenvolvimento local, testes, e ambientes de staging. Permite que você defina uma stack completa (banco de dados, cache, web server, etc) com facilidade e reprodutibilidade.
Os principais benefícios do Docker Compose são:
- Simplicidade: Uma único arquivo para toda a stack
- Reprodutibilidade: Mesmo ambiente em qualquer máquina
- Isolamento: Containers isolados em redes próprias
- Facilidade: Sem necessidade de lembrar comandos complexos
- Velocidade: Inicie múltiplos serviços com um comando
O fluxo de trabalho é simples: você escreve um `docker-compose.yml` descrevendo os serviços, depois executa `docker-compose up` para iniciá-los. Todos os containers são criados, conectados em rede e iniciados automaticamente.
Docker Compose é especialmente útil para criar ambientes de desenvolvimento que espelham o ambiente de produção, permitindo que problemas sejam detectados mais cedo.
Em resumo, Docker Compose simplifica o gerenciamento de múltiplos containers, tornando o desenvolvimento mais rápido, previsível e collaborativo! 🚀
2. Conceitos Fundamentais
Serviço (Service)
- Definição: Um container ou grupo de containers relacionados
- Exemplos: MySQL, Redis, Node.js, Nginx
- Configuração: Definido no docker-compose.yml
- Comunicação: Serviços se comunicam por nome de serviço
Volume (Volume)
- Definição: Armazenamento persistente para dados
- Tipos: Volumes nomeados ou mounts de host
- Uso: Dados de banco de dados, arquivos de aplicação
- Persistência: Dados survivem ao restart do container
Rede (Network)
- Definição: Conexão entre containers
- Padrão: Rede bridge automática por projeto
- DNS: Serviços se resolvem por nome
- Isolamento: Cada projeto tem sua própria rede
Arquivo docker-compose.yml
- Formato: YAML (indentação importa!)
- Versão: Especifica compatibilidade (v3.x é padrão)
- Localização: Raiz do projeto
- Nomes: docker-compose.yml ou docker-compose.yaml
3. Instalação do Docker e Docker Compose
Windows e Mac (Desktop):
# Docker Desktop já inclui Docker Compose
# Download em: https://www.docker.com/products/docker-desktop
# Verificar instalação
docker --version
docker-compose --version
# Deve retornar algo como:
# Docker version 24.0.0, build abcdef
# Docker Compose version 2.20.0
Linux (Ubuntu/Debian):
# Instalar Docker
sudo apt update
sudo apt install docker.io
# Instalar Docker Compose
sudo apt install docker-compose
# Adicionar usuário ao grupo docker (para não usar sudo)
sudo usermod -aG docker $USER
newgrp docker
# Testar instalação
docker --version
docker-compose --version
4. Estrutura do docker-compose.yml
Arquivo Básico:
version: '3.8' # Versão do Compose
services:
# Nome do serviço (como você irá referenciar)
mysql:
image: mysql:8.0 # Imagem Docker a usar
container_name: meu-mysql # Nome do container
environment: # Variáveis de ambiente
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: meu_banco
MYSQL_USER: usuario
MYSQL_PASSWORD: senha123
ports:
- "3306:3306" # Porta host:container
volumes:
- mysql_data:/var/lib/mysql # Volume para persistência
networks:
- minha_rede # Rede customizada
volumes:
# Define volumes que serão criados
mysql_data:
driver: local
networks:
# Define redes customizadas
minha_rede:
driver: bridge
5. Exemplo Prático: MySQL com Docker Compose
Vamos criar um ambiente MySQL completo para desenvolvimento.
docker-compose.yml - MySQL Simples:
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: mysql-dev
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: dev_db
MYSQL_USER: dev_user
MYSQL_PASSWORD: dev_pass123
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- dev_network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
volumes:
mysql_data:
driver: local
networks:
dev_network:
driver: bridge
Iniciar e Gerenciar:
# Iniciar os containers em background
docker-compose up -d
# Ver status dos containers
docker-compose ps
# Ver logs
docker-compose logs -f mysql
# Acessar o MySQL
docker-compose exec mysql mysql -u root -p dev_db
# Parar os containers
docker-compose stop
# Parar e remover containers
docker-compose down
# Remover também os volumes (CUIDADO - apaga dados!)
docker-compose down -v
Arquivo init.sql (Inicializar banco):
-- Arquivo: init.sql
-- Será executado automaticamente ao criar o container
CREATE TABLE IF NOT EXISTS usuarios (
id INT PRIMARY KEY AUTO_INCREMENT,
nome VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
criado_em TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO usuarios (nome, email) VALUES
('Ana Silva', 'ana@example.com'),
('Bruno Costa', 'bruno@example.com'),
('Carlos Souza', 'carlos@example.com');
6. PostgreSQL com Docker Compose
Alternativa ao MySQL com mais recursos avançados.
docker-compose.yml - PostgreSQL:
version: '3.8'
services:
postgres:
image: postgres:15-alpine
container_name: postgres-dev
environment:
POSTGRES_USER: dev_user
POSTGRES_PASSWORD: dev_pass123
POSTGRES_DB: dev_db
POSTGRES_INITDB_ARGS: "--encoding=UTF8"
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- dev_network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U dev_user"]
interval: 10s
timeout: 5s
retries: 5
# PgAdmin - Interface web para gerenciar PostgreSQL
pgadmin:
image: dpage/pgadmin4:latest
container_name: pgadmin-dev
environment:
PGADMIN_DEFAULT_EMAIL: admin@example.com
PGADMIN_DEFAULT_PASSWORD: admin123
ports:
- "5050:80"
networks:
- dev_network
depends_on:
- postgres
volumes:
postgres_data:
driver: local
networks:
dev_network:
driver: bridge
Acessar PgAdmin:
# Iniciar
docker-compose up -d
# Acessar PgAdmin em: http://localhost:5050
# Email: admin@example.com
# Senha: admin123
# Conectar ao PostgreSQL:
# Host: postgres (nome do serviço)
# Port: 5432
# Database: dev_db
# User: dev_user
# Password: dev_pass123
# Ou via CLI
docker-compose exec postgres psql -U dev_user -d dev_db
7. Stack Completa: Aplicação + Banco + Redis
Um exemplo real com múltiplos serviços para uma aplicação Java/Spring Boot.
docker-compose.yml - Stack Completa:
version: '3.8'
services:
# Banco de Dados MySQL
mysql:
image: mysql:8.0
container_name: app-mysql
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: app_db
MYSQL_USER: app_user
MYSQL_PASSWORD: app_pass123
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- app_network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
# Cache Redis
redis:
image: redis:7-alpine
container_name: app-redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- app_network
command: redis-server --appendonly yes
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
# Aplicação Java/Spring Boot
app:
build:
context: .
dockerfile: Dockerfile
container_name: app-server
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/app_db?useSSL=false
SPRING_DATASOURCE_USERNAME: app_user
SPRING_DATASOURCE_PASSWORD: app_pass123
SPRING_REDIS_HOST: redis
SPRING_REDIS_PORT: 6379
ports:
- "8080:8080"
volumes:
- ./src:/app/src
networks:
- app_network
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stopped
volumes:
mysql_data:
driver: local
redis_data:
driver: local
networks:
app_network:
driver: bridge
Dockerfile (para a aplicação Spring Boot):
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /app
# Copiar arquivos do projeto
COPY pom.xml .
COPY src ./src
# Build da aplicação
RUN mvn clean package -DskipTests
# Estágio final
FROM eclipse-temurin:17-jre
WORKDIR /app
# Copiar JAR do build anterior
COPY --from=builder /app/target/app.jar app.jar
# Expor porta
EXPOSE 8080
# Iniciar aplicação
ENTRYPOINT ["java", "-jar", "app.jar"]
Iniciar a Stack Completa:
# Iniciar todos os serviços
docker-compose up -d
# Ver status
docker-compose ps
# Ver logs de um serviço específico
docker-compose logs -f app
# Ver logs de todos
docker-compose logs -f
# Parar tudo
docker-compose down
# Parar e remover volumes
docker-compose down -v
8. Comandos Docker Compose Úteis
Gerenciamento de Containers:
# UP - Criar e iniciar containers
docker-compose up -d # Background
docker-compose up # Modo verbose
# DOWN - Parar e remover containers
docker-compose down # Mantém volumes
docker-compose down -v # Remove volumes também
# PS - Listar containers
docker-compose ps
# START/STOP - Iniciar/Parar containers
docker-compose start
docker-compose stop
# RESTART - Reiniciar containers
docker-compose restart
# LOGS - Ver logs
docker-compose logs -f # Todos
docker-compose logs -f mysql # Serviço específico
docker-compose logs --tail 50 # Últimas 50 linhas
# EXEC - Executar comando dentro do container
docker-compose exec mysql bash # Abrir shell
docker-compose exec mysql ls -la # Listar arquivos
# BUILD - Reconstruir imagens
docker-compose build
docker-compose build --no-cache # Sem cache
# PULL - Atualizar imagens
docker-compose pull
# RM - Remover containers parados
docker-compose rm
# CONFIG - Validar e exibir configuração
docker-compose config
9. Boas Práticas
✓ Use .env para Variáveis de Ambiente
- Crie arquivo `.env` na raiz do projeto
- Docker Compose lê automaticamente
- Não committe `.env` no git (adicione ao .gitignore)
✓ Use Healthchecks
- Verifique se serviço está realmente pronto
- Use `depends_on` com condition
- Evita problemas de inicialização
✓ Volumes para Desenvolvimento
- Mapeie seu código local em tempo real
- Evite reconstruir imagens a cada mudança
- Perfeito para desenvolvimento local
✓ Versionamento de Imagens
- Sempre especifique versão da imagem
- Evite usar `latest` em produção
- Garanta reprodutibilidade
10. Usando Arquivo .env
.env - Variáveis de Ambiente:
# .env
MYSQL_ROOT_PASSWORD=root123
MYSQL_DATABASE=app_db
MYSQL_USER=app_user
MYSQL_PASSWORD=app_pass123
REDIS_PORT=6379
SPRING_PORT=8080
SPRING_PROFILE=dev
docker-compose.yml com .env:
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7-alpine
ports:
- "${REDIS_PORT}:6379"
volumes:
- redis_data:/data
volumes:
mysql_data:
redis_data:
.gitignore - Proteger .env:
# .gitignore
.env
.env.local
.env.*.local
node_modules/
target/
*.log
.DS_Store
.vscode/
.idea/
11. Troubleshooting Comum
Problemas e Soluções:
# ❌ Problema: Porta já em uso
# Solução: Mude a porta no docker-compose.yml ou:
docker-compose down
sudo lsof -i :3306 # Ver qual processo usa porta
kill -9 PID
---
# ❌ Problema: Não consegue conectar ao banco
# Solução: Verifique healthcheck e dependências
docker-compose logs mysql
docker-compose exec mysql mysql -u root -p
---
# ❌ Problema: Container sai logo após iniciar
# Solução: Verifique logs
docker-compose logs app
# Procure por erros no console
---
# ❌ Problema: Volume não está funcionando
# Solução: Verifique sintaxe e permissões
docker-compose exec app ls -la /app
# Verifique sintaxe do volume no yml
---
# ❌ Problema: Rede não consegue se comunicar
# Solução: Use nome do serviço como hostname
# Correto: jdbc:mysql://mysql:3306/db
# Errado: jdbc:mysql://localhost:3306/db
---
# ❌ Problema: Mudanças no código não aparecem
# Solução: Verifique se volume está configurado
volumes:
- ./src:/app/src # Mapeie seu código local
---
# Limpar tudo e começar novamente
docker-compose down -v
docker system prune -a
docker-compose up -d --build
12. Exercícios Práticos
Exercício 1: MySQL + PhpMyAdmin
Crie um docker-compose com MySQL e PhpMyAdmin. Inicialize com dados de exemplo. Acesse via PhpMyAdmin e realize consultas.
Exercício 2: PostgreSQL + PgAdmin
Configure PostgreSQL com PgAdmin. Crie tabelas e dados via SQL. Pratique operações CRUD através do PgAdmin.
Exercício 3: Stack Multi-container
Crie uma aplicação Spring Boot que se conecta com MySQL e Redis. Configure docker-compose com todos os serviços, healthchecks e dependências.
Exercício 4: Usando .env
Refatore um docker-compose existente para usar arquivo .env. Crie variáveis para senhas, portas e nomes de bancos.
Exercício 5: Volumes e Persistência
Configure volumes nomeados para banco de dados. Teste que dados persistem após `docker-compose down`.
Conclusão
Docker Compose é essencial para desenvolvimento moderno, permitindo que todos na equipe tenham o mesmo ambiente.
Pontos-chave para lembrar:
- Um arquivo: docker-compose.yml define toda a stack
- Fácil setup: `docker-compose up -d` para começar
- Isolamento: Containers isolados em rede própria
- Reprodutibilidade: Mesmo ambiente em qualquer máquina
- Variáveis: Use .env para configurações sensíveis
- Healthchecks: Verifique se serviços estão prontos
Docker Compose é a ponte entre desenvolvimento local e produção. Domine-o para ser um desenvolvedor mais eficiente! 🚀