TechLead
Lesson 7 of 18
5 min read
Docker & DevOps

Docker Compose

Define and run multi-container applications with Docker Compose using declarative YAML configuration

What is Docker Compose?

Docker Compose is a tool for defining and running multi-container applications. Instead of manually running docker run commands with multiple flags, you describe your entire application stack in a single docker-compose.yml (or compose.yml) file.

Basic Compose File

# docker-compose.yml
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro

Full Stack Example

# docker-compose.yml
services:
  # PostgreSQL Database
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp
    volumes:
      - postgres-data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis Cache
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data

  # Backend API
  api:
    build:
      context: ./api
      dockerfile: Dockerfile
    ports:
      - "4000:4000"
    environment:
      DATABASE_URL: postgres://admin:secret@db:5432/myapp
      REDIS_URL: redis://redis:6379
      NODE_ENV: production
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    restart: unless-stopped

  # Frontend App
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      NEXT_PUBLIC_API_URL: http://localhost:4000
    depends_on:
      - api

volumes:
  postgres-data:
  redis-data:

Compose Commands

# Start all services
docker compose up

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

# Build and start
docker compose up --build

# Stop all services
docker compose down

# Stop and remove volumes
docker compose down -v

# View service logs
docker compose logs
docker compose logs -f api    # Follow specific service

# List running services
docker compose ps

# Restart a specific service
docker compose restart api

# Scale a service
docker compose up -d --scale api=3

# Execute a command in a service
docker compose exec api sh
docker compose exec db psql -U admin myapp

Development vs Production

# docker-compose.yml (base)
services:
  api:
    build: ./api
    environment:
      NODE_ENV: production

---
# docker-compose.override.yml (dev — auto-loaded)
services:
  api:
    build:
      context: ./api
      dockerfile: Dockerfile.dev
    volumes:
      - ./api/src:/app/src    # Live reload
    environment:
      NODE_ENV: development
      DEBUG: "true"
    command: npm run dev
# Development (uses override automatically)
docker compose up

# Production (only base file)
docker compose -f docker-compose.yml up -d

# Or use multiple compose files
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Environment Variables

# Using .env file (auto-loaded)
services:
  api:
    image: myapp:${APP_VERSION:-latest}
    environment:
      - DB_HOST=${DB_HOST}
      - DB_PASSWORD=${DB_PASSWORD}
    env_file:
      - .env
      - .env.local

Key Takeaways

  • ✅ Docker Compose defines your entire stack in one file
  • ✅ Use depends_on with health checks for reliable startup order
  • ✅ Use override files for dev-specific configuration
  • ✅ Named volumes in the top-level volumes section persist data

Continue Learning