fivenines
34/40
Lesson 34 · Orchestration

Compose: Declarative Applications

In one sentence: Compose replaces a fragile pile of run commands with one declarative file — services, networks, volumes — and a convergence engine that diffs your declaration against reality and applies only the difference.

You already know

  • Every noun in a compose file: images (P2), containers (P4), volumes (P5), networks (P6).
  • From Lesson 31: on a shared user-defined network, services find each other by name.

Say what, not how

An imperative deploy script encodes steps; when reality drifts (one container crashed, one image is stale), the script is wrong and humans improvise. A compose file encodes desired state: "these three services, on these networks, with these volumes." A service is a template for containers — image, config, mounts, networks — not a container itself; that indirection is what later lets one service mean five replicas. From one file, the engine derives the whole resource graph and creates a default network so every service can dial every other by service name.

Architecture — one file, expanded into resources
flowchart TB
  F["compose file (declared intent)
services: web, api, db
volumes: dbdata
networks: default"] F --> W["service web
image web:2 · port 443:8443"] F --> A["service api
image api:5 · env …"] F --> D["service db
image pg:16 · mount dbdata"] F --> NET["network: app_default
(auto-created, embedded DNS)"] F --> VOL[("volume: dbdata")] W --- NET A --- NET D --- NET D --- VOL

Up is a diff, not a script

up means converge: compare declared state with what exists, then create, recreate, or leave alone per resource. Running up twice in a row does nothing the second time — the fixed point is the definition of correctness. Change one service's image and only that service is recreated; the volume and network survive untouched:

Sequence — up, after editing only api's image tag
sequenceDiagram
  participant U as User
  participant C as Compose engine
  participant E as Engine API
  U->>C: up
  C->>E: inspect existing: network, volume, 3 containers
  E-->>C: all present; api runs image api:4, file says api:5
  C->>C: diff → only api differs
  C->>E: recreate api container (new image, same network + names)
  C->>E: web, db, network, volume: untouched
  C-->>U: converged — 1 changed, 4 unchanged
    

Anchor these

  • Declare state; let the engine compute the steps. Reruns are no-ops at the fixed point.
  • A service is a container template — the indirection that enables replicas later.
  • The auto-created per-app network + name-based DNS is what makes services composable.
Next step

See what actually stuck.

Take the practice scenarios now.