Skillversitas

Docker Compose

Docker Compose is a tool for defining and running multi-container applications using a YAML file.

docker-compose.yml Structure

version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    networks:
      - frontend

  api:
    build: ./backend
    environment:
      - DB_HOST=database
      - DB_PORT=5432
    depends_on:
      - database
    networks:
      - backend

  database:
    image: postgres:15
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret123
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - backend

networks:
  frontend:
  backend:

volumes:
  db-data:

Docker Compose Commands

# Run all services
docker-compose up -d

# Stop all services
docker-compose down

# View status
docker-compose ps

# View logs
docker-compose logs -f

# Rebuild
docker-compose up -d --build

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

# Execute a command in a container
docker-compose exec api bash
docker-compose exec database psql -U admin myapp

Service Configuration

services:
  app:
    build:
      context: ./app
      dockerfile: Dockerfile
      args:
        NODE_ENV: production
    image: myapp:1.0
    container_name: myapp-app
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DB_HOST=database
    env_file:
      - .env
    volumes:
      - ./app/src:/app/src
      - app-data:/app/data
    depends_on:
      - database
      - redis
    networks:
      - frontend
      - backend
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

Use Case: Application

version: '3.8'

services:
  # Frontend
  frontend:
    build: ./frontend
    ports:
      - "80:80"
    networks:
      - frontend
    depends_on:
      - api

  # Backend API
  api:
    build: ./backend
    environment:
      - DB_HOST=database
      - DB_PORT=5432
      - DB_NAME=myapp
      - REDIS_HOST=cache
    volumes:
      - ./backend/src:/app/src
    networks:
      - frontend
      - backend
    depends_on:
      - database
      - cache

  # Database
  database:
    image: postgres:15
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db-data:/var/lib/postgresql/data
      - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - backend

  # Cache
  cache:
    image: redis:7-alpine
    volumes:
      - cache-data:/data
    networks:
      - backend

  # Queue
  queue:
    image: rabbitmq:3-management
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: ${RABBIT_PASSWORD}
    ports:
      - "15672:15672"
    networks:
      - backend

networks:
  frontend:
  backend:

volumes:
  db-data:
  cache-data:

Environment Variables

# .env file
DB_PASSWORD=secret123
RABBIT_PASSWORD=rabbit456
REDIS_PASSWORD=redis789
# docker-compose.yml
services:
  db:
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}

Profiles

services:
  web:
    image: nginx:alpine

  debug:
    image: busybox
    profiles:
      - debug

# Run: docker-compose --profile debug up

Everyday Use Case

Case: A developer needs to run the stack for development.

# Run all services
docker-compose up -d

# View real-time logs
docker-compose logs -f api

# Enter a container
docker-compose exec api bash

# Run a migration
docker-compose exec api npm run migrate

# Stop all services
docker-compose down

Best Practices

  1. Use the latest version: version: '3.8'
  2. Define depends_on: For startup order
  3. Use healthchecks: To ensure a service is ready
  4. Separate environments: Use a .env file
  5. Use volumes: For persistent data
  6. Define networks: For isolation

Troubleshooting

Service won't start

# Check the logs
docker-compose logs service_name

# Check status
docker-compose ps

# Rebuild
docker-compose up -d --build

Port conflict

# Check which ports are in use
docker-compose ps

# Stop everything
docker-compose down

# Use a different port
docker-compose up -d -p 8080:80

Conclusion

Docker Compose makes managing multi-container applications easy. For applications, Compose ensures all services run correctly and are easy to maintain.