Skip to content

Docker_compose

Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services.

When applications need multiple containers (web app, database, cache, queue), managing them individually becomes complex:

┌─────────────────────────────────────────────────────────────────────────────┐
│ Without vs With Docker Compose │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Without Compose: With Compose: │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ docker run -d │ │ docker-compose │ │
│ │ --name web ... │ │ up -d │ │
│ │ docker run -d │ └────────┬────────┘ │
│ │ --name db ... │ │ │
│ │ docker run -d │ │ │
│ │ --name redis... │ │ │
│ │ docker run -d │ │ │
│ │ --name worker.. │ │ │
│ └─────────────────┘ ▼ │
│ ┌─────────────────┐ │
│ │ docker-compose │ │
│ │ .yml │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
docker-compose.yml
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "8080:80"
api:
image: myapi:latest
depends_on:
- db
environment:
- DATABASE_URL=postgres://db:5432/mydb
db:
image: postgres:15
environment:
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=mydb
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
# Use version '3' for Docker Engine 17.12.0+
# Use version '3.8' for newer features
version: '3.8'
services:
web:
image: nginx:1.25
# Or build from Dockerfile
build: .
# Or build with context and dockerfile
build:
context: ./dir
dockerfile: Dockerfile
services:
web:
ports:
# Short syntax
- "8080:80"
- "8443:443"
# Long syntax
- target: 8080
host: 0.0.0.0
protocol: tcp
services:
api:
environment:
# Short syntax
- NODE_ENV=production
- DATABASE_URL=postgres://db:5432/mydb
# Long syntax
- name: NODE_ENV
value: production
services:
web:
volumes:
# Short syntax
- ./html:/usr/share/nginx/html:ro
- nginx-data:/var/log/nginx
# Long syntax
- type: volume
source: nginx-data
target: /var/log/nginx
read_only: true
services:
web:
networks:
- frontend
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
services:
web:
depends_on:
- db
- redis
db:
image: postgres:15
redis:
image: redis:7
Terminal window
# Start all services (detached mode)
docker-compose up -d
# Start specific service
docker-compose up -d web
# Start with build
docker-compose up --build
# Recreate containers
docker-compose up -d --force-recreate
Terminal window
# Stop services
docker-compose stop
# Stop and remove containers
docker-compose down
# Remove volumes too
docker-compose down -v
# Remove images
docker-compose down --rmi local
# View logs
docker-compose logs -f
# View logs for specific service
docker-compose logs -f web
Terminal window
# Run command in service
docker-compose exec web sh
# Run one-off command
docker-compose run --rm web npm test
Terminal window
# Scale service
docker-compose up -d --scale web=3
# Note: Requires proper load balancing setup
Terminal window
# Validate configuration
docker-compose config
# List containers
docker-compose ps
# Pull images
docker-compose pull
services:
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
services:
web:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
services:
db:
image: postgres:15
secrets:
- db_password
secrets:
db_password:
file: ./db_password.txt
services:
web:
image: nginx
monitor:
image: prometheus
profiles:
- monitoring

Run with profile:

Terminal window
docker-compose --profile monitoring up
# .env file
COMPOSE_PROJECT_NAME=myapp
POSTGRES_PASSWORD=secret
# docker-compose.yml
services:
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
# File structure
docker-compose.yml # Base config
docker-compose.override.yml # Local overrides
docker-compose.prod.yml # Production overrides
docker-compose.yml
services:
web:
image: myapp:latest
environment:
- ENV=development
# docker-compose.override.yml (auto-loaded)
services:
web:
ports:
- "3000:3000"
volumes:
- .:/app
docker-compose.prod.yml
services:
web:
image: myapp:v1.0
restart: always
ports:
- "80:80"
Terminal window
# Development (uses override automatically)
docker-compose up -d
# Production
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
docker-compose.yml
version: '3.8'
services:
# Reverse Proxy
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- web
networks:
- frontend
# Web Application
web:
build: .
environment:
- DATABASE_URL=postgresql://user:password@db:5432/mydb
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
networks:
- frontend
- backend
# Database
db:
image: postgres:15
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydb
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
interval: 10s
timeout: 5s
retries: 5
networks:
- backend
# Cache
redis:
image: redis:7-alpine
networks:
- backend
# Background Worker
worker:
build: .
command: npm run worker
environment:
- DATABASE_URL=postgresql://user:password@db:5432/mydb
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
networks:
- backend
networks:
frontend:
backend:
volumes:
db-data:

In this chapter, you learned:

  • What Docker Compose is and why to use it
  • Writing docker-compose.yml files
  • Service configuration options
  • Docker Compose commands
  • Advanced features (health checks, secrets, profiles)