fivenines
8/40

Guided Problem

MiniDock Build 05: Store Shared Image Content Once

Time
20m
Level
foundation
Artifacts
not specified
Progress0%
Lesson 8 · Images

Content Addressing

Design claim: Naming content by a digest makes identity, verification, immutability, and deduplication consequences of the same rule.

Starting model

  • You can read an image graph and identify which object owns runtime metadata and layer order.
  • The useful vocabulary at this point is deliberately small: content address, SHA-256, digest, deduplication.

Names that move cannot verify content

Many images reuse identical base layers, and every downloaded object must be verified before it becomes trusted local content. Treat the release as data with identity and history, not as the accidental contents of one machine. Reuse is safe only after that data model is precise.

The tempting shortcut is straightforward: store blobs under mutable human-readable names. The shortcut looks efficient until immutable history, shared content, or reproducibility becomes observable. A mutable name can point to different bytes over time and cannot prove that a cache hit or transfer returned the requested object. The constraint turns a convenient file operation into an identity or ordering bug.

Make the identifier a claim about bytes

In a content-addressed store you don't choose names — the bytes choose. Store a layer, and its name is sha256(bytes). Three properties fall out at once. Immutability: "modifying" an object is impossible; different bytes are a different name. Verification: anyone holding the blob can re-hash it and detect tampering or corruption — no signatures needed for integrity. Deduplication: if two images share a base layer, the bytes hash identically, so the store holds one copy no matter how many manifests reference it.

The engine computes a cryptographic digest over bytes and uses that digest as the object's address and verification expectation. The mechanism makes inputs and resulting content explicit, allowing later stages to reuse facts instead of trusting names or mutable directories.

Read the structure from references toward immutable content, noting where ordering or private state changes the meaning of an otherwise shared object.

Architecture — two images, one shared blob
  flowchart TB
    MA["manifest: web-app"] --> LA["sha256:11aa…
web app files"] MA --> BASE["sha256:77ff…
base OS layer
(stored ONCE)"] MB["manifest: worker-app"] --> LB["sha256:22bb…
worker files"] MB --> BASE style BASE fill:#eaf1fe,stroke:#1d63ed,stroke-width:2px

It shows multiple manifests converging on one digest-addressed layer. Its central claim is that one digest denotes one byte sequence, and bytes enter trusted storage only after matching it; the labels therefore describe authority rather than decorative grouping.

Verification belongs on both sides of transfer

Because names are fingerprints, the engine can accept blobs from anywhere — an untrusted mirror, a cache, a peer — and still be safe, as long as the digest it expected came from somewhere trusted. This is the foundation the registry protocol (Part 3) is built on:

Before transfer the client checks its local digest set; after transfer it hashes the bytes, rejects mismatches, and atomically installs one copy. Follow identity through the operation and ask which completed fact authorizes each reuse or transition.

The second figure tests the same model in motion: it orders local lookup, download, hashing, rejection, and atomic installation.

Sequence — verifying a downloaded layer
  sequenceDiagram
    participant E as Engine
    participant S as Any source (even untrusted)
    E->>S: give me blob sha256:77ff…
    S-->>E: bytes (2 GB)
    E->>E: recompute sha256 over received bytes
    alt hash equals 77ff…
      E->>E: store blob — verified, provenance irrelevant
    else mismatch
      E->>E: discard — corrupted or malicious
    end
      

It orders local lookup, download, hashing, rejection, and atomic installation. The ordering is valid only when it continues to preserve the stated invariant under retries and interruption.

Transport success is not content success

A registry returns corrupted bytes for a requested digest, so the client must discard them even if the transport reported success. A partial or stale result must remain distinguishable from a complete image state; otherwise the cache or store begins to lie.

One digest denotes one byte sequence, and bytes enter trusted storage only after matching it. The invariant is phrased in bytes, ownership, or completed prefixes so it remains true across storage implementations.

Let MiniDock store facts, not promises

MiniDock can share image content safely without a separate deduplication database. MiniDock can adopt the content rule without preselecting the learner's attachment point.

What carries forward

  • One digest denotes one byte sequence, and bytes enter trusted storage only after matching it.
  • Store shared image content once and reject bytes that do not match their requested identity.
  • 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.