Docker Compose Template Examples

Below are examples of docker-compose.yaml files demonstrating common configurations, including a version utilizing secrets for sensitive data.

Standard Docker Compose Template

This example showcases many core features of Docker Compose for defining a multi-container application.

# Docker Compose file version is implicit in modern Compose files
# This file defines a multi-container application setup

services:
  # Main application service
  app:
    # Build the image from a Dockerfile in the current directory
    build:
      context: .
      dockerfile: ./Dockerfile
      # Build arguments that can be passed to the Dockerfile during build
      args:
        BUILD_ENV: production

    # Or use a pre-built image instead of building
    # image: myapp:latest

    # Container name (optional, otherwise generated automatically)
    container_name: my-application

    # Restart policy (never, always, on-failure, unless-stopped)
    restart: unless-stopped

    # Port mapping - HOST:CONTAINER format
    ports:
      - "8080:80"
      - "443:443"

    # Environment variables
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - DB_USER=user
      - DB_PASSWORD=password # Note: Avoid hardcoding secrets here in real projects

    # Or use an env file instead
    # env_file:
    #   - .env

    # Mount volumes - HOST:CONTAINER format
    volumes:
      - ./app:/app # Mount local code for development (if needed)
      - app-data:/var/data # Mount named volume

    # Define dependencies - this service will start after db
    depends_on:
      db:
        condition: service_healthy # Wait until db is healthy

    # Connect to these networks
    networks:
      - frontend
      - backend

    # Health check to determine if container is running properly
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

    # Resource constraints (optional, mainly for Swarm/Kubernetes via Compose)
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

  # Database service
  db:
    image: postgres:14
    container_name: database
    restart: always

    # Expose ports only to other services on the same Docker network, not to host
    expose:
      - "5432"

    # Environment variables specific to this service
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password # Note: Avoid hardcoding secrets
      - POSTGRES_DB=mydb

    # Persist database data using a named volume
    volumes:
      - db-data:/var/lib/postgresql/data

    # Health check for database
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5

    networks:
      - backend

  # Redis cache service example
  cache:
    image: redis:alpine
    container_name: redis-cache
    restart: always
    networks:
      - backend
    # Command to run when container starts
    command: redis-server --save 60 1 --loglevel warning

# Define named volumes for persistent data
volumes:
  app-data:
    # You can specify driver and options for volumes
    driver: local
  db-data:
    driver: local

# Define networks for isolation between services
networks:
  frontend:
    # You can use the default bridge driver
    driver: bridge
  backend:
    driver: bridge
    # Optional network configuration
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16

Key Functionalities Included:

  • Service Definitions: Defines individual containers (app, db, cache). [Services]
  • Build Configuration: Shows how to build an image from a Dockerfile using build context, dockerfile path, and build args.
  • Image Usage: Demonstrates using pre-built images (e.g., postgres:14, redis:alpine).
  • Container Naming: Uses container_name for predictable naming.
  • Restart Policies: Configures container restart behavior (restart: unless-stopped).
  • Port Mapping: Exposes container ports to the host (ports) or only to other services (expose).
  • Environment Variables: Sets configuration via environment (or env_file).
  • Volumes: Mounts host directories (./app:/app - often for dev) and named volumes (db-data:/var/...) for persistence. [Volumes]
  • Dependencies & Startup Order: Uses depends_on with condition: service_healthy to control startup sequence. [Startup Order]
  • Networking: Defines custom bridge networks (frontend, backend) for service isolation and communication. [Networking]
  • Health Checks: Uses healthcheck to verify container health before marking it as ready or restarting it.
  • Resource Constraints: Shows optional deploy.resources.limits for controlling CPU/memory (primarily for Swarm).
  • Commands: Specifies a custom command for the cache service.

You can customize this template based on your specific application needs. For more detailed information about specific Compose file options, refer to the Compose file reference.


Docker Compose Template with Secrets

This version demonstrates how to securely manage sensitive data like passwords and API keys using Docker secrets, avoiding hardcoding them in the Compose file or environment variables.

# Docker Compose file version is implicit in modern Compose files
# This file defines a multi-container application setup using secrets

services:
  # Main application service
  app:
    build:
      context: .
      dockerfile: ./Dockerfile
      args:
        BUILD_ENV: production
      # Build secrets - available only during build time (requires BuildKit)
      secrets:
        - build_secret

    container_name: my-application
    restart: unless-stopped
    ports:
      - "8080:80"
      - "443:443"

    # Environment variables
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - DB_USER=user
      # Reference to secret file path instead of hardcoded password
      - DB_PASSWORD_FILE=/run/secrets/db_password # App reads password from this file

    volumes:
      - ./app:/app
      - app-data:/var/data

    depends_on:
      db:
        condition: service_healthy

    networks:
      - frontend
      - backend

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

    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

    # Secrets to be mounted into the running container's filesystem
    secrets:
      - db_password # Grant access to the 'db_password' secret
      - api_key     # Grant access to the 'api_key' secret

  # Database service
  db:
    image: postgres:14
    container_name: database
    restart: always
    expose:
      - "5432"

    # Environment variables specific to this service
    environment:
      - POSTGRES_USER=user
      # Reference to secret file instead of hardcoded password
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password # Postgres reads password from this file
      - POSTGRES_DB=mydb

    volumes:
      - db-data:/var/lib/postgresql/data

    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5

    networks:
      - backend

    # Secrets for the database service
    secrets:
      - db_password # Grant access to the 'db_password' secret

  # Redis cache service example (unchanged from previous example)
  cache:
    image: redis:alpine
    container_name: redis-cache
    restart: always
    networks:
      - backend
    command: redis-server --save 60 1 --loglevel warning

# Define named volumes for persistent data (unchanged)
volumes:
  app-data:
    driver: local
  db-data:
    driver: local

# Define networks for isolation between services (unchanged)
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16

# Define secrets for sensitive data (top-level declaration)
secrets:
  # File-based secret (read from a file on the host)
  db_password:
    file: ./secrets/db_password.txt # Path to the secret file on the host

  # Environment variable-based secret (reads from host environment)
  api_key:
    environment: API_KEY_ENV_VAR # Name of host env var containing the secret

  # External secret (managed outside of Compose, e.g., by Swarm)
  # ssl_cert:
  #   external: true

  # Build-time only secret (defined here, used in service build section)
  build_secret:
    file: ./secrets/build_secret.txt

Key Differences & Secret Handling:

  • Top-Level secrets Block: Defines all secrets available to the Compose application. Specifies how each secret is sourced (file, environment, external). [Secrets]
  • Service-Level secrets Block: Grants specific services access to secrets defined in the top-level block. Secrets granted here are mounted into the container's filesystem at /run/secrets/<secret_name> by default.
  • Referencing Secrets in Environment Variables: Instead of hardcoding passwords, services are configured to read the secret from the mounted file (e.g., DB_PASSWORD_FILE=/run/secrets/db_password for the app service, POSTGRES_PASSWORD_FILE=/run/secrets/db_password for the db service). The application code or entrypoint script needs to be adapted to read the secret from this file path.
  • Build-Time Secrets: The build.secrets section allows securely passing secrets *during* the image build process (using RUN --mount=type=secret... in the Dockerfile). These secrets are *not* available in the final image or running container unless explicitly copied. This requires Docker BuildKit.
  • Security Benefit: Secrets are not stored in the Compose file, environment variables (which can be inspected), or container image layers. They are managed externally or mounted temporarily into the running container's filesystem.

Important: Ensure the source files (like ./secrets/db_password.txt) or environment variables (like API_KEY_ENV_VAR) exist on the host machine where you run docker compose up, and protect these source files appropriately (e.g., add them to .gitignore).