SuperAPI AI Directory

docker-syntax-compose-resources

Deployment & operations

View repository

Updated 10-15 22:17

About this skill

docker-syntax-compose-resources

Quick Reference

Top-Level Resource Elements

Element Purpose Default Behavior
networks Define named networks for service communication Compose creates implicit default network
volumes Define named volumes for persistent data Created on docker compose up if missing
configs Define non-sensitive configuration data Mounted at /<config-name> with mode 0444
secrets Define sensitive data (passwords, certificates) Mounted at /run/secrets/<secret-name>

Network Driver Comparison

Driver Scope Use Case Multi-Host
bridge Single host Default. Isolated network between containers No
host Single host Container shares host network stack directly No
overlay Multi-host Swarm service communication across nodes Yes
macvlan Single host Container gets own MAC address on physical network No
none Single host Completely disable networking No

Config vs Secret Comparison

Attribute Config Secret
Purpose Non-sensitive configuration Sensitive credentials
Default mount path /<config-name> /run/secrets/<secret-name>
Default permissions 0444 (world-readable) 0444 (world-readable)
Source options file, environment, content file, environment
Customizable mount Yes (target, uid, gid, mode) Yes (target, uid, gid, mode)
content inline Yes (Compose 2.23.1+) No

Critical Warnings

NEVER use anonymous volumes for data that must persist -- anonymous volumes are recreated on docker compose down and all data is lost. ALWAYS define named volumes in the top-level volumes section.

NEVER omit the top-level declaration for a named volume, config, or secret -- referencing an undeclared resource in a service causes a Compose validation error. ALWAYS declare every resource at the top level.

NEVER set external: true on a resource without ensuring it exists before running docker compose up -- Compose does NOT create external resources and errors immediately if they are missing.

NEVER combine external: true with driver, driver_opts, file, content, or other creation attributes -- when external is set, only name is relevant alongside it. Compose rejects files with additional fields on external resources.

ALWAYS use reverse-DNS notation for resource labels (e.g., com.example.description) -- this prevents naming collisions with labels from other tools.


Decision Trees

Which Resource Type to Use

Need to store data persistently across container restarts?
├─ Yes → Use a VOLUME (top-level `volumes`)
│   ├─ Data owned by this Compose project? → Define normally
│   └─ Data shared across projects? → Use `external: true`
└─ No → Need to inject file-based configuration?
    ├─ Contains sensitive data (passwords, keys, certs)?
    │   └─ Yes → Use a SECRET (top-level `secrets`)
    └─ Non-sensitive configuration?
        └─ Yes → Use a CONFIG (top-level `configs`)

Which Network Driver to Use

Need containers to communicate?
├─ Single Docker host?
│   ├─ Standard container isolation → driver: bridge (default)
│   ├─ Container needs host network performance → driver: host
│   └─ Container needs own MAC on physical LAN → driver: macvlan
├─ Multiple Docker hosts (Swarm)?
│   └─ driver: overlay
└─ Container must have no network access?
    └─ driver: none

External vs Managed Resources

Is the resource created outside this Compose project?
├─ Yes → external: true
│   ├─ Name matches Compose key? → Just set external: true
│   └─ Different name? → Add name: "actual-name"
└─ No → Let Compose manage creation and lifecycle
    ├─ Need custom driver? → Set driver + driver_opts
    ├─ Need custom subnet? → Set ipam.config
    └─ Default behavior sufficient? → Declare with empty body

Top-Level Networks

Basic Network Definition

networks:
  frontend:
  backend:
    driver: bridge

An empty declaration uses the default bridge driver.

Network with IPAM Configuration

networks:
  app-net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16
          ip_range: 172.28.5.0/24
          gateway: 172.28.5.254
          aux_addresses:
            host1: 172.28.1.5

Network Attributes

networks:
  internal-net:
    internal: true        # Externally isolated -- no internet access
    attachable: true       # Standalone containers can attach
    enable_ipv6: true      # Enable IPv6
    labels:
      com.example.project: "myapp"
    name: "custom-net-name"
    driver_opts:
      com.docker.network.bridge.host_binding_ipv4: "127.0.0.1"

External Network

networks:
  shared:
    external: true
    name: "${NETWORK_ID}"    # Variable interpolation supported

Customizing the Default Network

networks:
  default:
    name: my-app-network
    driver: bridge
    driver_opts:
      com.docker.network.bridge.host_binding_ipv4: "127.0.0.1"

Service-Level Network Configuration

services:
  app:
    networks:
      backend:
        aliases:
          - app-alias
          - api
        ipv4_address: 172.16.238.10
        ipv6_address: 2001:3984:3989::10
        priority: 1000

Top-Level Volumes

Basic Volume Definition

volumes:
  db-data:
  cache:
    driver: local

Volume with NFS Driver

volumes:
  nfs-data:
    driver_opts:
      type: "nfs"
      o: "addr=10.40.0.199,nolock,soft,rw"
      device: ":/docker/example"

External Volume

volumes:
  shared-data:
    external: true
    name: actual-volume-name

Volume with Labels

volumes:
  db-data:
    labels:
      com.example.description: "Database volume"
      com.example.department: "IT/Ops"
    name: "${DATABASE_VOLUME}"

Top-Level Configs and Secrets

Config Sources

configs:
  from-file:
    file: ./httpd.conf
  from-env:
    environment: "CONFIG_VALUE"       # Compose 2.23.1+
  from-inline:
    content: |                         # Compose 2.23.1+
      debug=${DEBUG}
      app.name=${COMPOSE_PROJECT_NAME}
  from-external:
    external: true
    name: "${HTTP_CONFIG_KEY}"

Secret Sources

secrets:
  from-file:
    file: ./server.cert
  from-env:
    environment: "OAUTH_TOKEN"
  from-external:
    external: true
    name: "${SECRET_KEY}"

Mounting in Services

services:
  web:
    configs:
      - from-file                            # Short: mounts at /<config-name>
      - source: from-inline
        target: /etc/app/config.properties
        uid: "1000"
        gid: "1000"
        mode: 0440
    secrets:
      - from-file                            # Short: mounts at /run/secrets/<name>
      - source: from-env
        target: oauth-token
        uid: "103"
        gid: "103"
        mode: 0440

Network Isolation Pattern

services:
  proxy:
    image: nginx
    networks:
      - frontend
  app:
    image: myapp
    networks:
      - frontend
      - backend
  db:
    image: postgres
    networks:
      - backend

networks:
  frontend:
  backend:
    internal: true    # No external access for database network

In this pattern, proxy CANNOT reach db -- only app bridges both networks. Setting internal: true on backend prevents containers on that network from reaching the internet.


Complete Resource Example

services:
  web:
    image: nginx
    configs:
      - source: nginx-config
        target: /etc/nginx/nginx.conf
        mode: 0440
    secrets:
      - tls-cert
      - source: tls-key
        target: /etc/ssl/private/server.key
        mode: 0400
    volumes:
      - static-files:/usr/share/nginx/html:ro
    networks:
      frontend:
        aliases:
          - webserver

  app:
    image: myapp
    volumes:
      - app-data:/data
    networks:
      - frontend
      - backend

  db:
    image: postgres
    volumes:
      - db-data:/var/lib/postgresql/data
    secrets:
      - db-password
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true

volumes:
  db-data:
  app-data:
  static-files:

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

secrets:
  tls-cert:
    file: ./certs/server.crt
  tls-key:
    file: ./certs/server.key
  db-password:
    environment: POSTGRES_PASSWORD

Reference Links

Official Sources