Docker Compose Cheatsheet - Most useful commands with examples

BTW, docker-compose is different from docker compose...

Page content

Here’s a Docker Compose cheatsheet with annotated examples to help you master Compose files and commands quickly.

This guide is part of Developer Tools: The Complete Guide to Modern Development Workflows.

Prerequisites

Docker Engine must be installed before you use Compose. On Ubuntu, follow Install Docker on Ubuntu to choose the right install method and set up the docker compose plugin.

docker-compose schema

Compose File Reference: docker-compose.yml

Core structure:

version: '3'       # Compose file format version

services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"   # Host port 8080:Container port 80
  db:
    image: postgres
    environment:            # Environment variables
      POSTGRES_PASSWORD: example
    volumes:
      - db_data:/var/lib/postgresql/data

networks:          # Custom network
  appnet:
    driver: bridge

volumes:           # Named volume
  db_data:
  • services: Each container in your multi-container app. In the example above we have two services: web and db. For individual container operations, see the Docker Cheatsheet.
  • networks & volumes: Define isolated networks and persistent storage - we have appnet network and db_data volume here.

Examples

Single service with port mapping

services:
  app:
    build: .
    ports:
      - "8000:80"   # Host port 8000:Container port 80

Exposes app on host port 8000 and builds from Dockerfile in current directory.

Multi-service with shared volume and custom network

version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - type: bind
        source: ./app
        target: /app
    networks:
      - mynet
  db:
    image: postgres
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - mynet

networks:
  mynet:

volumes:
  db_data:

Web and DB on same network; DB uses persisted named volume - db_data.

Using build context and Dockerfile path

You can build docker image on demand from the specified in docker-compose.yam Dockerfile.

services:
  app:
    build:
      context: .
      dockerfile: docker/MyDockerfile

Sharing data between services

services:
  web:
    image: nginx
    volumes:
      - shared_data:/usr/share/nginx/html
  worker:
    image: myworker
    volumes:
      - shared_data:/usr/src/app/data

volumes:
  shared_data:

Both services access same volume (for static files or data exchanges) - shared_data.

Advanced Compose File Options

  • environment: Set ENV variables for containers.
  • depends_on: Control service startup order.
  • deploy.replicas: Scale service in Swarm mode.

Example:

services:
  web:
    image: nginx
    deploy:
      replicas: 3
    depends_on:
      - db

Starts 3 web instances; only controls startup order (not readiness).

Essential Docker Compose Commands

Command Description Example Usage
docker-compose up Creates and starts containers docker-compose up
docker-compose up -d Run in background docker-compose up -d
docker-compose exec Execute command in running container docker-compose exec web bash
docker-compose build Build/rebuild images docker-compose build
docker-compose down Stop and remove containers, networks, volumes, and images docker-compose down
docker-compose logs -f View and follow logs docker-compose logs -f
docker-compose ps List running containers docker-compose ps
docker-compose run Run one-off commands (bypasses command in Compose file) docker-compose run web python manage.py migrate
docker-compose stop Stop running containers (can restart with start) docker-compose stop
docker-compose restart Restart services docker-compose restart web
docker-compose pull Pull service images docker-compose pull
docker-compose rm Remove stopped service containers docker-compose rm web
docker-compose config Validate and view Compose file docker-compose config
docker-compose up --scale web=3 Start multiple instances of a service docker-compose up --scale web=3

Common Compose Patterns

  • Databases with persistent data

    services:
      mysql:
        image: mysql
        environment:
          MYSQL_ROOT_PASSWORD: password
        volumes:
          - mysql_data:/var/lib/mysql
    
    volumes:
      mysql_data:
    

    DB data persists in the mysql_data volume across container restarts.

  • Bind mounting code for development

    services:
      app:
        build: .
        volumes:
          - .:/app
    

    Live-edit code on host, auto-reflected in container.

Useful Flags

  • -d: Detach mode (run in background).
  • --build: Force rebuild images before starting.
  • --force-recreate: Recreate containers even if unchanged.
  • --remove-orphans: Remove containers not defined in Compose file.

Defining and Customizing Services

You can define and customize services, networks, and volumes in Docker Compose by leveraging the docker-compose.yml file, which centralizes all your application’s configuration and orchestration needs.

  • Services are defined under the services key.
  • Each service represents a container configuration, where you can set:
    • Image: Select an image from Docker Hub or another registry.
    • Ports: Map container ports to host ports.
    • Environment variables: Pass configuration values.
    • Volumes: Persist data or share files/folders with the host or other services.
    • Networks: Control which networks the service can access.

Example:

services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"   # Host port 8080:Container port 80
    environment:
      - NGINX_HOST=localhost
    volumes:
      - web_data:/usr/share/nginx/html
    networks:
      - frontend

  db:
    image: postgres:13
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - backend
  • Here, the web service uses the nginx image, sets an environment variable, attaches a volume, opens port 80 as 8080 on the host, and connects to the frontend network. The db service does something similar for PostgreSQL.

Customizing Networks

  • Networks control which services can communicate. Compose creates a default network, but you can define more, specify custom drivers, set options, and determine which service joins which network for fine-grained isolation.
  • Define networks at the top level under networks, and list which networks a service should attach to with the service-level networks key.

Example:

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.host_binding_ipv4: "127.0.0.1"
  • Attach networks to services:
services:
  app:
    networks:
      - frontend
      - backend
  db:
    networks:
      - backend
  • This setup allows the app service to access both users on the frontend and backend networks, while db is only accessible within the backend.

Customizing Volumes

  • Volumes are defined under the top-level volumes key. Mount them to containers using the volumes key under a service.
  • Volumes can be named, use custom drivers, and be shared across multiple services for data persistence and sharing.

Example:

volumes:
  web_data:                # Named volume for web content
  db_data:                 # Named volume for database

services:
  web:
    volumes:
      - web_data:/usr/share/nginx/html

  db:
    volumes:
      - db_data:/var/lib/postgresql/data
  • In this example, web_data is persisted and available to any container that mounts it. db_data ensures database data is never lost upon container recreation.
  • You can define bind-mounts with custom driver options for advanced cases:
volumes:
  db_data:
    driver: local
    driver_opts:
      type: none
      device: /data/db_data
      o: bind
  • This configuration sets up a bind-mount from the host path /data/db_data into the container.

Summary of Best Practices:

  • Use the service name as a DNS hostname for inter-service communication.
  • Attach services to multiple networks as needed to control access.
  • Use named volumes for persistent storage and data sharing.
  • Define everything using YAML, enabling version control and easy deployment scripts.
  • For container management and visualization, consider Install Portainer on Linux.

Multiple compose files

To organize complex multi-service setups in Docker Compose, you can use multiple compose files and override files, allowing modular, environment-specific, and scalable configurations. Here’s how this works:

  1. Base and Override File Structure
  • Create a base file (compose.yaml or docker-compose.yml) containing all common, default service definitions.
  • Add environment-specific override files (e.g., docker-compose.override.yml, docker-compose.dev.yml, docker-compose.prod.yml).

Example file structure:

/project-directory
|-- docker-compose.yml           # Base configuration
|-- docker-compose.override.yml  # Local/dev overrides (applied automatically)
|-- docker-compose.prod.yml      # Production overrides
|-- docker-compose.test.yml      # Test overrides (if needed)

The base config defines core services, while each override customizes settings for a specific environment or case.

  1. How File Overrides Work
  • Merging: When you run docker compose up, Docker Compose merges the base with any overrides in order; subsequent files override, extend, or add to settings in previous files.
  • Overriding Fields: If a service or field is defined in multiple files, the last-specified file’s value is used. New fields are added.

Example merge:

  • docker-compose.yml:
    services:
      web:
        image: myapp
        ports:
          - "8000:80"
    
  • docker-compose.override.yml:
    services:
      web:
        environment:
          - DEBUG=true
    
  • Result: The web service uses both the base image and port plus the overridden DEBUG environment variable.
  1. Command Usage for Multiple Files
  • Default behavior: If present, Docker Compose automatically loads docker-compose.override.yml together with docker-compose.yml when you run any command.
  • Specifying files manually: Use -f flags to control which files are merged and in what order:
    docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
    
    • This ignores the default override and uses the production-specific settings.
  1. Practical Organization Strategies
  • Environment separation: Use one override per environment: dev, test, prod, etc.
  • Microservices and teams: Break configuration into separate files for different services or teams, and combine as needed.
  • Feature toggles: Additional files can introduce or remove optional services or configuration for temporary needs (e.g., a compose.debug.yml for extra logging).
  1. Benefits
  • Clarity: Keeps individual files small and focused.
  • Scalability: Easily add new services, environments, or settings.
  • Maintainability: Only change or review relevant sections for a given deployment.
  1. Example: Switching Environments

Development:

docker compose -f docker-compose.yml -f docker-compose.dev.yml up

Production:

docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Each environment gets only the configuration necessary for it, with all shared config in the base file.

Organizing complex Compose setups with multiple files - and leveraging the override/merge system-ensures modularity, environment-specific customization, and easy scalability for large, multi-service Docker applications.

For production deployment on a single Linux host — boot on startup, clean shutdown, updates, and log rotation — see Run Docker Compose as a Linux Service with systemd. For a comparison with Podman Quadlet, see Podman Quadlet vs Docker Compose for Linux Services.

Subscribe

Get new posts on AI systems, Infrastructure, and AI engineering.