# Anatomy of a Compose File — Docker Compose

Source: https://www.skillbyai.com/en/docker-compose/i-file

> Services, volumes, networks, secrets.

## Top-level sections

A Compose file (`compose.yaml` by default) has top-level **services** (each one a container definition: image or build, ports, environment, volumes, dependencies, health checks), plus **volumes**, **networks**, **secrets** and **configs** shared between services. An optional `name` sets the project name. The old top-level `version:` key is obsolete in the current Compose Specification and can be dropped. Extension fields starting with `x-` hold reusable snippets.

## The demo shop's compose.yaml

This file is used throughout the course: a web front end, an API, a PostgreSQL database and an optional admin tool.

```yaml
name: shop

x-common-env: &common-env
  TZ: Asia/Kolkata
  LOG_LEVEL: ${LOG_LEVEL:-info}

services:
  web:
    build:
      context: ./web
      target: runtime
    ports:
      - "8080:80"
    depends_on:
      api:
        condition: service_healthy
    environment:
      <<: *common-env
      API_URL: http://api:3000

  api:
    build: ./api
    environment:
      <<: *common-env
      DATABASE_URL: postgres://shop:${DB_PASSWORD:?set DB_PASSWORD in .env}@db:5432/shop
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 10s
      timeout: 3s
      retries: 5
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:${PG_VERSION:-17}
    environment:
      POSTGRES_USER: shop
      POSTGRES_DB: shop
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U shop -d shop"]
      interval: 5s
      retries: 10

  adminer:
    image: adminer:4
    profiles: ["debug"]
    ports:
      - "8081:8080"

volumes:
  db-data:

secrets:
  db_password:
    file: ./secrets/db_password.txt
```

## Drop the version key

Modern Compose ignores the top-level version field; keeping it only confuses readers about which features are available.

**Quiz:** Which top-level section defines the containers to run?

- [x] services
- [ ] volumes
- [ ] secrets
- [ ] x-common-env

*Answer:* services. Each service becomes one or more containers.
