Service Dependencies
Service Dependencies
depends_on Basics
depends_on controls service startup order:
services:
api:
image: myapi
depends_on:
- db # db starts before api
- redis # redis starts before api
db:
image: postgres:16
redis:
image: redis:7
Limitation: depends_on only waits for the container to START, not for the service to be ready. A PostgreSQL container starts immediately but takes seconds to initialize.
Health Check Dependencies (Compose V2.1+)
services:
api:
image: myapi
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
start_period: 10s
redis:
image: redis:7
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
Health Check Conditions
| Condition | Description |
|---|---|
service_started |
Container has started (default) |
service_healthy |
Container health check passes |
service_completed_successfully |
Container ran and exited 0 |
Complete Example
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
start_period: 15s
volumes:
- pgdata:/var/lib/postgresql/data
api:
build: ./api
depends_on:
db:
condition: service_healthy
environment:
DATABASE_URL: postgresql://postgres:secret@db:5432/myapp
nginx:
image: nginx:1.25
depends_on:
api:
condition: service_started
ports:
- "80:80"
Common Health Checks
# PostgreSQL
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
# MySQL
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
# Redis
healthcheck:
test: ["CMD", "redis-cli", "ping"]
# MongoDB
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongosh --quiet
# Elasticsearch
healthcheck:
test: curl -f http://localhost:9200/_cluster/health || exit 1
# Custom Node.js app
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', r => r.statusCode === 200 ? process.exit(0) : process.exit(1))"]
# HTTP check
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
# TCP check
healthcheck:
test: ["CMD", "nc", "-z", "localhost", "3306"]
Service Lifecycle Management
Service Lifecycle Management
Starting and Stopping Services
# Start all services
docker compose up -d
# Start specific services
docker compose up -d api db
# Stop all services
docker compose down
# Stop and remove volumes
docker compose down -v
# Stop and remove images
docker compose down --rmi all
# Restart a specific service
docker compose restart api
# Pause/unpause all services
docker compose pause
docker compose unpause
Scaling Services
# Scale a service to 3 instances
docker compose up -d --scale api=3
# Check running instances
docker compose ps
# NAME SERVICE STATUS
# myproject-api-1 api running
# myproject-api-2 api running
# myproject-api-3 api running
# Note: Scaled services share the same image
# Port conflicts may occur if not using random ports
Exec and Run Commands
# Execute command in running service
docker compose exec api bash
# Run one-off command
docker compose run api npm test
# Run without attaching to output
docker compose exec -d api python manage.py migrate
# Run as specific user
docker compose exec --user root api apt-get update
View Service Status
# Show all services
docker compose ps
# Show with details
docker compose ps --format json
# Filter by status
docker compose ps --filter status=running
# View service logs
docker compose logs api
# Follow logs for specific service
docker compose logs -f api
# Show last 100 lines
docker compose logs --tail 100 api
Graceful Shutdown
Compose sends SIGTERM to containers on docker compose down. Configure graceful shutdown:
services:
api:
image: myapi
stop_grace_period: 30s # 30 seconds before SIGKILL
Profiles
services:
web:
image: nginx
# Always starts (no profile)
debug-tools:
image: busybox
profiles:
- debug
monitoring:
image: prometheus
profiles:
- production
# Start only default services
docker compose up -d
# Start with debug tools
docker compose --profile debug up -d
# Start with production services
docker compose --profile production up -d
# Start all profiles
docker compose --profile "*" up -d