Skip to content

Docker Compose

Docker Compose is a tool for defining and running multi-container Docker applications. Use a YAML file to configure your application's services, networks, and volumes.

Quick Reference

TaskCommand
Start servicesdocker-compose up -d
Stop servicesdocker-compose down
View logsdocker-compose logs -f
List servicesdocker-compose ps
Execute commanddocker-compose exec <service> <command>
Build imagesdocker-compose build
Pull imagesdocker-compose pull
Restart servicesdocker-compose restart

Installation

Linux

bash
# Download latest version
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# Make executable
sudo chmod +x /usr/local/bin/docker-compose

# Verify installation
docker-compose --version

macOS and Windows

Docker Compose is included with Docker Desktop.

Basic Usage

Simple docker-compose.yml

yaml
version: "3.8"

services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html

  db:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Start and Stop

bash
# Start all services (detached)
docker-compose up -d

# Start specific service
docker-compose up -d web

# Stop all services
docker-compose down

# Stop and remove volumes
docker-compose down -v

Common Commands

Starting Services

bash
# Start in foreground (see logs)
docker-compose up

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

# Rebuild images before starting
docker-compose up --build

# Force recreate containers
docker-compose up --force-recreate

# Start specific services
docker-compose up -d web db

Stopping Services

bash
# Stop services (keep containers)
docker-compose stop

# Stop and remove containers
docker-compose down

# Stop and remove containers, networks, and volumes
docker-compose down -v

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

Viewing Logs

bash
# View logs from all services
docker-compose logs

# Follow logs in real-time
docker-compose logs -f

# View logs from specific service
docker-compose logs -f web

# Show last N lines
docker-compose logs --tail=100

# Show timestamps
docker-compose logs -t

Executing Commands

bash
# Execute command in running service
docker-compose exec web bash

# Run one-off command (create new container)
docker-compose run --rm web bash

# Example from README (interactive mode)
docker-compose run --rm service1

Managing Services

bash
# List running services
docker-compose ps

# List all services (including stopped)
docker-compose ps -a

# Restart services
docker-compose restart

# Restart specific service
docker-compose restart web

# Pause services
docker-compose pause

# Unpause services
docker-compose unpause

docker-compose.yml Examples

Interactive Service (from README)

yaml
version: "3"
services:
  service1:
    image: mcr.microsoft.com/dotnet/core/runtime:3.1
    stdin_open: true
    tty: true
    command: "/bin/bash"
bash
# Run interactively
docker-compose run --rm service1

Web Application with Database

yaml
version: "3.8"

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://db:5432/myapp
    depends_on:
      - db
    volumes:
      - ./src:/app/src
    restart: unless-stopped

  db:
    image: postgres:15
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  postgres_data:

Development Stack

yaml
version: "3.8"

services:
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - ./frontend/src:/app/src
      - /app/node_modules
    environment:
      - REACT_APP_API_URL=http://localhost:8000

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile.dev
    ports:
      - "8000:8000"
    volumes:
      - ./backend:/app
    environment:
      - DEBUG=true
      - DATABASE_URL=postgresql://postgres:password@db:5432/app
    depends_on:
      - db
      - redis

  db:
    image: postgres:15
    environment:
      POSTGRES_DB: app
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  postgres_data:

Microservices Architecture

yaml
version: "3.8"

services:
  api-gateway:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - auth-service
      - user-service
      - order-service

  auth-service:
    build: ./services/auth
    environment:
      - SERVICE_NAME=auth
      - JWT_SECRET=${JWT_SECRET}
    networks:
      - backend

  user-service:
    build: ./services/user
    environment:
      - SERVICE_NAME=user
      - DB_HOST=postgres
    depends_on:
      - postgres
    networks:
      - backend

  order-service:
    build: ./services/order
    environment:
      - SERVICE_NAME=order
      - DB_HOST=postgres
    depends_on:
      - postgres
      - rabbitmq
    networks:
      - backend

  postgres:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    networks:
      - backend

  rabbitmq:
    image: rabbitmq:3-management
    ports:
      - "15672:15672"
    networks:
      - backend

networks:
  backend:

volumes:
  pgdata:

Advanced Features

Environment Variables

Using .env file:

env
# .env
POSTGRES_PASSWORD=secret
API_KEY=abc123
NODE_ENV=production
yaml
# docker-compose.yml
version: "3.8"

services:
  app:
    image: myapp
    environment:
      - DB_PASSWORD=${POSTGRES_PASSWORD}
      - API_KEY=${API_KEY}
      - NODE_ENV=${NODE_ENV}

Build Configuration

yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.prod
      args:
        - BUILD_VERSION=1.0.0
        - NODE_VERSION=20
      cache_from:
        - myapp:latest
      target: production

Health Checks

yaml
services:
  app:
    image: myapp
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Networks

yaml
version: "3.8"

services:
  frontend:
    image: frontend
    networks:
      - public

  backend:
    image: backend
    networks:
      - public
      - private

  database:
    image: postgres
    networks:
      - private

networks:
  public:
    driver: bridge
  private:
    driver: bridge
    internal: true

Resource Limits

yaml
services:
  app:
    image: myapp
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 1G
        reservations:
          cpus: '1'
          memory: 512M

Common Workflows

Development Workflow

bash
# Start development environment
docker-compose up -d

# View logs
docker-compose logs -f app

# Make code changes (automatically reflected if using volumes)

# Rebuild after dependency changes
docker-compose up -d --build

# Run tests
docker-compose exec app npm test

# Stop environment
docker-compose down

Production Deployment

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

# View service status
docker-compose ps

# Scale services
docker-compose up -d --scale worker=3

# Update services
docker-compose pull
docker-compose up -d

# View logs
docker-compose logs -f

Database Migrations

bash
# Run migrations
docker-compose exec app npm run migrate

# Create database backup
docker-compose exec db pg_dump -U user dbname > backup.sql

# Restore database
docker-compose exec -T db psql -U user dbname < backup.sql

Multiple Compose Files

Override Files

bash
# Base configuration
# docker-compose.yml (production defaults)

# Development overrides
# docker-compose.override.yml (automatically loaded)

# Start with defaults + overrides
docker-compose up -d

# Use specific file
docker-compose -f docker-compose.prod.yml up -d

# Combine multiple files
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d

Example Override

docker-compose.yml:

yaml
version: "3.8"
services:
  app:
    image: myapp:latest
    environment:
      - NODE_ENV=production

docker-compose.override.yml:

yaml
version: "3.8"
services:
  app:
    build: .
    volumes:
      - ./src:/app/src
    environment:
      - NODE_ENV=development
    ports:
      - "9229:9229"  # Debug port

Troubleshooting

Services Won't Start

bash
# Check configuration syntax
docker-compose config

# View detailed logs
docker-compose logs

# Rebuild images
docker-compose build --no-cache

# Force recreate
docker-compose up -d --force-recreate

Network Issues

bash
# List networks
docker network ls

# Inspect network
docker network inspect <network_name>

# Recreate networks
docker-compose down
docker-compose up -d

Volume Issues

bash
# List volumes
docker volume ls

# Inspect volume
docker volume inspect <volume_name>

# Remove unused volumes
docker volume prune

# Remove all compose volumes
docker-compose down -v

Performance Issues

bash
# Check resource usage
docker stats

# Limit resources in compose file (see Resource Limits section)

# Check logs for errors
docker-compose logs --tail=100

Best Practices

File Organization

  1. Use .env for environment-specific variables
  2. Create separate compose files for different environments
  3. Use docker-compose.override.yml for local development
  4. Keep sensitive data out of compose files

Service Design

  1. One concern per service
  2. Use depends_on for service dependencies
  3. Implement health checks
  4. Use restart policies appropriately

Development

  1. Use volumes for code hot-reloading
  2. Expose debug ports in development
  3. Use override files for dev-specific config
  4. Don't commit .env files with secrets

Production

  1. Use specific image tags (not latest)
  2. Set resource limits
  3. Implement logging and monitoring
  4. Use secrets management
  5. Regular backups of volumes

See Also

External Resources

Released under the MIT License.