Skip to main content

Docker Compose

Multi-container application orchestration with Docker Compose configurations and commands.

Basic Docker Compose

Simple docker-compose.yml

version: '3.8'

services:
web:
build: .
ports:
- '3000:3000'
environment:
- NODE_ENV=production
depends_on:
- db

db:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data

volumes:
postgres_data:

Multi-Service Application

version: '3.8'

services:
web:
build:
context: .
dockerfile: Dockerfile
ports:
- '3000:3000'
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:password@db:5432/myapp
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
networks:
- app-network
restart: unless-stopped

db:
image: postgres:13-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- app-network
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U user -d myapp']
interval: 30s
timeout: 10s
retries: 3

redis:
image: redis:7-alpine
ports:
- '6379:6379'
networks:
- app-network
command: redis-server --appendonly yes
volumes:
- redis_data:/data

nginx:
image: nginx:alpine
ports:
- '80:80'
- '443:443'
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- web
networks:
- app-network

volumes:
postgres_data:
redis_data:

networks:
app-network:
driver: bridge

Compose Commands

Basic Operations

# Start services
docker-compose up

# Start in background (detached)
docker-compose up -d

# Build and start
docker-compose up --build

# Start specific services
docker-compose up web db

# Stop services
docker-compose down

# Stop and remove volumes
docker-compose down -v

# Stop and remove images
docker-compose down --rmi all

Service Management

# List running services
docker-compose ps

# Show service logs
docker-compose logs

# Follow logs for specific service
docker-compose logs -f web

# Follow logs for multiple services
docker-compose logs -f web db

# Show logs with timestamps
docker-compose logs -t web

# Restart services
docker-compose restart

# Restart specific service
docker-compose restart web

Scaling Services

# Scale service to multiple instances
docker-compose up --scale web=3

# Scale multiple services
docker-compose up --scale web=3 --scale worker=2

# Scale down
docker-compose up --scale web=1

Build Operations

# Build or rebuild services
docker-compose build

# Build specific service
docker-compose build web

# Build without cache
docker-compose build --no-cache

# Build with progress output
docker-compose build --progress plain

# Pull latest images
docker-compose pull

# Pull specific service image
docker-compose pull db

Advanced Compose Configuration

Environment Variables

version: '3.8'

services:
web:
build: .
environment:
# Direct assignment
- NODE_ENV=production
- DEBUG=false

# From host environment
- API_KEY=${API_KEY}
- DATABASE_URL

# From .env file
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}

# Environment file
env_file:
- .env
- .env.local

Using .env File

# .env file
NODE_ENV=production
POSTGRES_PASSWORD=secretpassword
API_KEY=your-api-key
COMPOSE_PROJECT_NAME=myapp

Volume Configurations

version: '3.8'

services:
web:
image: nginx
volumes:
# Named volume
- web_data:/var/www/html

# Bind mount
- ./src:/app/src
- ./config:/app/config:ro # Read-only

# Anonymous volume
- /app/node_modules

# Tmpfs mount
- type: tmpfs
target: /tmp
tmpfs:
size: 1000000000 # 1GB

volumes:
web_data:
driver: local
driver_opts:
type: nfs
o: addr=10.40.0.199,rw
device: ':/path/to/dir'

Network Configuration

version: '3.8'

services:
web:
image: nginx
networks:
- frontend
- backend
ports:
- '80:80'

db:
image: postgres
networks:
backend:
aliases:
- database
- postgres-server

networks:
frontend:
driver: bridge
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
external-network:
external: true

Health Checks

version: '3.8'

services:
web:
build: .
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3000/health']
interval: 30s
timeout: 10s
retries: 3
start_period: 60s

db:
image: postgres:13
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U postgres']
interval: 10s
timeout: 5s
retries: 5

redis:
image: redis:alpine
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 10s
timeout: 3s
retries: 3

Resource Limits

version: '3.8'

services:
web:
image: nginx
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s

Development vs Production

Development Configuration

# docker-compose.dev.yml
version: '3.8'

services:
web:
build:
context: .
target: development
volumes:
- ./src:/app/src # Live code reloading
- ./package.json:/app/package.json
environment:
- NODE_ENV=development
- DEBUG=true
ports:
- '3000:3000'
- '9229:9229' # Debug port
command: npm run dev

db:
image: postgres:13
ports:
- '5432:5432' # Expose for debugging

Production Configuration

# docker-compose.prod.yml
version: '3.8'

services:
web:
build:
context: .
target: production
environment:
- NODE_ENV=production
restart: unless-stopped
# No volume mounts or debug ports

db:
image: postgres:13
restart: unless-stopped
# No exposed ports

Override Files

# Use development override
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up

# Use production override
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# Multiple override files
docker-compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.local.yml up

Compose File Validation

Validate Configuration

# Validate compose file
docker-compose config

# Validate and show resolved configuration
docker-compose config --services

# Validate specific file
docker-compose -f docker-compose.prod.yml config

# Check for unused volumes
docker-compose config --volumes

# Resolve and display environment variables
docker-compose config --resolve-env-vars

Debugging Compose Applications

Debugging Commands

# Run command in service
docker-compose exec web /bin/bash

# Run one-off command
docker-compose run web npm test

# Run without dependencies
docker-compose run --no-deps web npm install

# Override entrypoint
docker-compose run --entrypoint /bin/bash web

# Check service status
docker-compose ps

# View service events
docker-compose events

Troubleshooting

# Check service health
docker-compose ps
docker-compose logs service_name

# Recreate services
docker-compose up --force-recreate

# Remove everything and start fresh
docker-compose down -v --remove-orphans
docker-compose up --build

# Debug networking
docker-compose exec web ping db
docker-compose exec web nslookup db

Production Deployment

Production Best Practices

version: '3.8'

services:
web:
image: myapp:${VERSION:-latest}
restart: unless-stopped
environment:
- NODE_ENV=production
secrets:
- api_key
- db_password
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '3'
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3000/health']
interval: 30s
timeout: 10s
retries: 3

secrets:
api_key:
external: true
db_password:
external: true

Deploy Commands

# Deploy with specific version
VERSION=1.2.3 docker-compose up -d

# Rolling update
docker-compose up -d --no-deps web

# Update specific service
docker-compose pull web
docker-compose up -d --no-deps web

Quick Reference

Essential Commands

  • docker-compose up -d - Start services in background
  • docker-compose down - Stop and remove services
  • docker-compose logs -f - Follow service logs
  • docker-compose exec service bash - Access service shell
  • docker-compose ps - List running services
  • docker-compose build - Build/rebuild services

File Structure

project/
├── docker-compose.yml # Base configuration
├── docker-compose.override.yml # Local development overrides
├── docker-compose.prod.yml # Production configuration
├── .env # Environment variables
└── .env.example # Environment template

Best Practices

  • Use specific image tags in production
  • Implement health checks for all services
  • Use secrets for sensitive data
  • Set resource limits for production
  • Use multi-stage builds for optimization
  • Implement proper logging configuration
  • Always use restart policies in production