fivenines
26/40
Lesson 26 · Storage

Volume Lifecycle and Drivers

In one sentence: Volumes are first-class objects with their own lifecycle — created, attached, detached, removed — deliberately decoupled from any container's lifecycle, and provisioned through a pluggable driver interface.

You already know

  • From Lesson 25: a volume is engine-owned storage, the default for precious data.
  • From Lesson 17: reference counting and reachability decide what's safe to delete.

Decoupled on purpose

The whole point of a volume is to outlive containers, so its lifecycle can't be nested inside theirs. The engine tracks each volume with a reference count of attached containers: remove a container and the volume detaches but persists (refcount decrements); a volume is only removable when its refcount is zero, and even then only by an explicit command or prune — never as a side effect. Ten containers can attach one volume simultaneously (shared state — useful, and a consistency footgun the app must handle). The corner case every engine faces: run -v data:/db where data doesn't exist yet — auto-create it, because requiring a separate create step first breaks the common path.

Architecture — volume states and the refcount
stateDiagram-v2
  [*] --> Exists: create (or auto-create on first use)
  Exists --> Attached: container starts with -v (refcount 1+)
  Attached --> Attached: more containers attach (refcount++)
  Attached --> Exists: last container removed (refcount 0)
  Exists --> [*]: explicit volume rm / prune
  note right of Exists
    refcount 0 = "dangling" —
    still never auto-deleted
  end note
    

The driver seam

"Give me a directory to mount" is an interface, not an implementation. The default local driver makes a host directory; an NFS driver mounts a remote share; a cloud driver attaches a network disk. The engine speaks four verbs — create, mount, unmount, remove — and never knows which backend answers:

Sequence — run -v data:/db with a driver, volume doesn't exist yet
sequenceDiagram
  participant E as Engine
  participant VS as Volume store
  participant DR as Driver (local / nfs / cloud)
  participant C as Container setup
  E->>VS: does volume "data" exist?
  VS-->>E: no
  E->>DR: create("data")
  DR-->>E: ready
  E->>DR: mount("data")
  DR-->>E: host path /mnt/…/data
  E->>C: bind that path over /db in the rootfs
  E->>VS: refcount("data") = 1
  note over VS: container rm later → refcount 0,
volume and bytes remain

Anchor these

  • Volume lifecycle is deliberately independent; refcounts link it to containers.
  • Deletion is always explicit — dangling ≠ deletable-automatically.
  • Four verbs (create/mount/unmount/remove) form the driver seam; backends are swappable.
Next step

See what actually stuck.

Take the practice scenarios now.