Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Docker Compose

Overview

Docker Compose is a tool for defining and running multi-container applications. Instead of managing containers individually with multiple docker run commands, you define your entire application stack in a single YAML file.

This makes it easy to:

  • Start/stop all services with one command
  • Define relationships between containers
  • Share configurations across team members
  • Recreate consistent environments

Prerequisites

Example: Web App with Database

Create a docker-compose.yml file:

services:
  web:
    image: nginx
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html
    depends_on:
      - db

  db:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

This defines:

  • A web server (nginx) on port 80
  • A PostgreSQL database with persistent storage
  • The web server waits for the database to start first

Start all services:

docker compose up -d

Stop and remove all services:

docker compose down

View running services and logs:

docker compose ps                # List running services
docker compose logs              # View logs from all services
docker compose logs -f web       # Follow logs for specific service

Volumes

Named Volumes

Docker manages the storage location. Data persists even when containers are removed:

services:
  db:
    image: postgres:15
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Bind Mounts

Map a host directory to a container directory. Changes on the host immediately appear in the container:

services:
  web:
    image: nginx
    volumes:
      - ./html:/usr/share/nginx/html

This is useful for development - edit files locally and see changes immediately.

Volume Commands

List all volumes:

docker volume ls

Show volume details:

docker volume inspect <name>

Remove a volume:

docker volume rm <name>

Remove all unused volumes:

docker volume prune

Networking

Containers in the same Compose file can communicate using service names as hostnames:

services:
  web:
    image: myapp
    environment:
      DATABASE_URL: postgres://db:5432/myapp

  db:
    image: postgres:15

The web container can reach the database at db:5432 (not localhost). Docker Compose automatically creates a network for all services.

Environment Variables

Pass environment variables to containers:

services:
  app:
    image: myapp
    environment:
      NODE_ENV: production
      API_KEY: secret123
      DATABASE_URL: postgres://db:5432/myapp

Or load from a file:

services:
  app:
    image: myapp
    env_file:
      - .env

Building Custom Images

Build images from a Dockerfile:

services:
  app:
    build: .
    ports:
      - "3000:3000"

Or specify build context and Dockerfile:

services:
  app:
    build:
      context: ./app
      dockerfile: Dockerfile.prod
    ports:
      - "3000:3000"