fivenines
19/40

Guided Problem

MiniDock Build 15: Complete One Run or Clean It Up

Time
30m
Level
advanced
Artifacts
not specified
Progress0%
Lesson 19 · Runtime

docker run: The Full Picture

Design claim: A run request is a coordinated workflow whose partial steps require explicit ownership and cleanup.

Starting model

  • You can serialize lifecycle commands and events into one legal container state.
  • The useful vocabulary at this point is deliberately small: run coordinator, root filesystem, network attachment, runtime bundle.

Convenient syntax hides distributed work

One user command must resolve content, allocate storage and networking, persist state, start a process, and attach streams. Runtime behavior unfolds over time, so state and ownership must remain valid after the initiating request has returned.

The tempting shortcut is straightforward: implement run as one opaque call that either returns a container or throws. The shortcut confuses one command or connection with the longer-lived process and resources it happens to touch. The workflow crosses independently failing subsystems, and earlier allocations remain when a later step fails. Asynchronous exit, retry, disconnect, or timeout exposes that mismatch immediately.

Give the workflow a durable spine

This is the course's midpoint summit — no new concepts, only composition. The order is forced by data dependencies: you can't mount layers you don't have, can't write a runtime bundle without a mounted rootfs and a network to reference, can't start what isn't created. Each lesson you've done is one arrow:

The daemon decomposes run into ordered, idempotent stages with a container record that coordinates progress and compensation. The mechanism records the durable fact separately from transient control and lets events update the model when reality changes.

Read the static view as custody and the dynamic view as evidence crossing that custody boundary.

Architecture — the assembly line behind one command
  flowchart TB
    A["1· resolve image
(reference store; pull if missing — L15)"] B["2· mount overlay
(image lowers + new upper — L9)"] C["3· allocate network
(sandbox + IP — Part 6)"] D["4· write bundle
(rootfs path + config: cmd, env, limits)"] E["5· runtime chain
(manager → shim → runc — L3)"] F["6· kernel setup
(namespaces L4, cgroups L5, seccomp L6)"] G["7· exec app — state: Running (L18)"] A --> B --> D C --> D D --> E --> F --> G

It places image, storage, network, runtime, and stream services around one coordinator. Its central claim is that one run request produces one completed container or a recoverable record of every resource that still needs cleanup; the labels therefore describe authority rather than decorative grouping.

Establish prerequisites before exposing success

This is the course's midpoint summit — no new concepts, only composition. The order is forced by data dependencies: you can't mount layers you don't have, can't write a runtime bundle without a mounted rootfs and a network to reference, can't start what isn't created. Each lesson you've done is one arrow:

Resolve image, prepare snapshot, create metadata, allocate network, assemble an OCI bundle, invoke the runtime chain, and connect the requested streams. The sequence matters because lifecycle decisions made from stale evidence become illegal or destructive operations.

The second figure tests the same model in motion: it orders allocation and launch while making the failure and cleanup edges visible.

Sequence — minidock run api:2.2, all layers visible
  sequenceDiagram
    participant CLI as CLI
    participant D as Daemon
    participant N as Net allocator
    participant M as Manager
    participant S as Shim
    participant R as Runtime
    CLI->>D: run api:2.2
    D->>D: resolve tag, then check layers (pull if missing)
    D->>D: mount overlay: lowers + fresh upper
    D->>N: create sandbox, assign IP
    N-->>D: eth0 ready
    D->>M: create container (bundle)
    M->>S: spawn shim
    S->>R: create: namespaces, cgroups, filters
    R->>R: exec app, then runtime exits
    S-->>M: running (pid)
    M-->>D: started
    D-->>CLI: container id, attached stream
      

It orders allocation and launch while making the failure and cleanup edges visible. The ordering is valid only when it continues to preserve the stated invariant under retries and interruption.

Failure leaves obligations, not mystery

Network allocation succeeds but process creation fails, so retry or cleanup must not leak an endpoint or create a duplicate container. The failure case is authoritative input to the state model, not an exception to be hidden behind a successful command response.

One run request produces one completed container or a recoverable record of every resource that still needs cleanup. The reusable rule keeps process reality, operator intent, and retained resources from collapsing into one status flag.

Assemble MiniDock's run path

MiniDock now composes prior subsystems through an explicit transaction-like workflow without pretending they share one transaction. MiniDock must preserve the lifecycle guarantee while leaving the current integration move to the learner.

What carries forward

  • One run request produces one completed container or a recoverable record of every resource that still needs cleanup.
  • Produce either one supervised running container or no resources from a failed run attempt.
  • The rejected shortcut remains a diagnostic: if the design starts depending on it again, the original constraint has probably been lost.
Next step

See what actually stuck.

Take the practice scenarios now.