Docker Compose — Top-Level Keys

2 minute read

A compose.yml file has several top-level keys that define different aspects of your application stack. This page explains each one.


The Five Top-Level Keys

# compose.yml — all top-level keys
name: myapp              # Optional: project name

services:                # REQUIRED: container definitions
  web:
    image: nginx
  db:
    image: postgres

volumes:                 # Optional: named volumes
  db-data:

networks:                # Optional: custom networks
  backend:

configs:                 # Optional: configuration files
  nginx-conf:
    file: ./nginx.conf

secrets:                 # Optional: sensitive data
  db-password:
    file: ./db-password.txt

services (Required)

The services: key defines your containers. This is the only required top-level key. Every service becomes a running container.

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

  api:
    build: ./api
    ports:
      - "3000:3000"

  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret

Each key under services: is a service name that you choose. It becomes the hostname for DNS resolution within the Compose network.


volumes (Optional)

The volumes: key defines named volumes for persistent data:

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

volumes:
  db-data:           # Named volume declaration

Named volumes persist data across docker compose down and docker compose up cycles. Without them, database data would be lost when containers are recreated.

┌──────────────────────────────────┐
│  Named Volume: db-data           │
│  ┌────────────────────────┐      │
│  │ /var/lib/postgresql/data│      │
│  │ tables, indexes, WAL    │      │
│  └────────────────────────┘      │
│                                  │
│  Survives: docker compose down   │
│  Removed:  docker compose down -v│
└──────────────────────────────────┘

networks (Optional)

The networks: key defines custom networks for service isolation:

services:
  web:
    networks:
      - frontend
  api:
    networks:
      - frontend
      - backend
  db:
    networks:
      - backend

networks:
  frontend:
  backend:
┌─────── frontend ───────┐
│  ┌─────┐   ┌─────┐    │
│  │ web │───│ api │    │
│  └─────┘   └──┬──┘    │
└───────────────┼────────┘
                │
┌─────── backend ────────┐
│           ┌──┴──┐      │
│           │ api │      │
│           └──┬──┘      │
│           ┌──┴──┐      │
│           │ db  │      │
│           └─────┘      │
└────────────────────────┘

web can talk to api (frontend network)
api can talk to db  (backend network)
web CANNOT talk to db (different networks)

If you don’t define any custom networks, Compose creates a default network that all services join automatically.


configs (Optional)

The configs: key mounts configuration files into containers:

services:
  web:
    image: nginx
    configs:
      - source: nginx-conf
        target: /etc/nginx/nginx.conf

configs:
  nginx-conf:
    file: ./nginx.conf

Configs are similar to bind mounts but are designed for configuration data and are immutable at runtime.


secrets (Optional)

The secrets: key handles sensitive data:

services:
  db:
    image: postgres:16
    secrets:
      - db-password
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db-password

secrets:
  db-password:
    file: ./db-password.txt

Secrets are mounted as files at /run/secrets/<name> inside the container. They’re more secure than environment variables because they don’t appear in docker inspect output.


Summary

Key Purpose Required
name: Project name Optional
services: Container definitions Yes
volumes: Named persistent volumes Optional
networks: Custom network isolation Optional
configs: Configuration files Optional
secrets: Sensitive data Optional

Quick Reference

Item Detail
services Container definitions — the only required key
volumes Named volumes for persistent data
networks Custom network isolation between services
configs Configuration files mounted into containers
secrets Sensitive data at /run/secrets/
name Project name (overrides directory name)