Docker Compose¶
🎼 Learning Objectives
- Write Docker Compose files
- Orchestrate multi-container applications
- Configure services and dependencies
- Use Compose for development and production
Orchestrate multi-container applications with Docker Compose.
Compose Best Practices
Use version 3.8 for latest features. Separate services logically. Use environment variables for configuration. Use health checks for service dependencies. Keep compose files in version control.
Development vs Production
Use override files (docker-compose.override.yml) for development-specific settings. Use separate compose files for production. Never commit secrets - use environment files or secrets management.
Introduction¶
Docker Compose allows you to define and run multi-container Docker applications using YAML files.
Why Docker Compose?¶
- Simplified orchestration: Define services in one file
- Environment management: Easy configuration per environment
- Service dependencies: Automatic service ordering
- Networking: Automatic network creation
- Scaling: Easy to scale services
Basic Compose File¶
Simple Example¶
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
db:
image: postgres:13
environment:
POSTGRES_PASSWORD: secret
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Running Compose¶
# Start services
docker-compose up
# Start in detached mode
docker-compose up -d
# Stop services
docker-compose down
# View logs
docker-compose logs -f
Service Configuration¶
Build from Dockerfile¶
services:
web:
build:
context: .
dockerfile: Dockerfile
args:
NODE_VERSION: 16
ports:
- "3000:3000"
environment:
- NODE_ENV=production
Environment Variables¶
services:
app:
image: myapp
environment:
- DATABASE_URL=postgres://db:5432/mydb
- REDIS_URL=redis://redis:6379
env_file:
- .env
- .env.production
Dependencies¶
services:
web:
build: .
depends_on:
- db
- redis
ports:
- "8000:8000"
db:
image: postgres:13
environment:
POSTGRES_DB: mydb
redis:
image: redis:alpine
Note
depends_on only waits for container start, not service readiness.
Health Checks¶
services:
web:
image: nginx
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
app:
build: .
depends_on:
web:
condition: service_healthy
Networking¶
Custom Networks¶
services:
web:
image: nginx
networks:
- frontend
- backend
api:
image: api
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
External Networks¶
Volumes¶
Named Volumes¶
services:
db:
image: postgres
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
driver: local
Bind Mounts¶
Advanced Patterns¶
Multi-Environment¶
# docker-compose.yml
version: '3.8'
services:
app:
build: .
env_file:
- .env.${ENV:-development}
# docker-compose.prod.yml
version: '3.8'
services:
app:
restart: always
deploy:
replicas: 3
Service Scaling¶
services:
web:
image: nginx
deploy:
replicas: 3
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
Override Files¶
# docker-compose.override.yml (auto-loaded)
services:
web:
volumes:
- ./src:/app/src # Development mount
environment:
- DEBUG=true
Production Compose¶
Full Example¶
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- web
restart: unless-stopped
web:
build:
context: .
dockerfile: Dockerfile.prod
environment:
- DATABASE_URL=${DATABASE_URL}
- REDIS_URL=${REDIS_URL}
depends_on:
- db
- redis
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
db:
image: postgres:13
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
volumes:
postgres_data:
redis_data:
networks:
default:
driver: bridge
Compose Commands¶
Management¶
# Start services
docker-compose up -d
# Stop services
docker-compose down
# Restart service
docker-compose restart web
# Scale service
docker-compose up -d --scale web=3
# View logs
docker-compose logs -f web
# Execute command
docker-compose exec web bash
# Pull images
docker-compose pull
# Build images
docker-compose build
# Remove stopped containers
docker-compose rm
Inspection¶
# List services
docker-compose ps
# View configuration
docker-compose config
# Validate configuration
docker-compose config --quiet
Best Practices¶
- Use version 3.8 for latest features
- Separate environments with override files
- Use health checks for service dependencies
- Set resource limits in production
- Use secrets for sensitive data
- Version control compose files
- Document service dependencies
Exercises¶
- Create a compose file for a web app with database
- Add health checks and service dependencies
- Set up multi-environment configuration
- Scale a service and verify load balancing
Previous: Volumes and Data Management | Next: Security