Guided Problem
MiniDock Build 06: Give Containers Private Writable Views
- Time
- 20m
- Level
- foundation
- Artifacts
- not specified
Union Filesystems
Design claim: A union filesystem gives each container a private writable view while retaining shared immutable image layers.
Starting model
- You can store shared image content once and reject bytes that do not match their requested identity.
- The useful vocabulary at this point is deliberately small: union filesystem, overlay, lower layer, upper layer.
Sharing and mutability pull in opposite directions
Many containers must start from the same image without copying its entire filesystem or allowing one container to modify another. 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: copy every image into a private directory before startup. The shortcut looks efficient until immutable history, shared content, or reproducibility becomes observable. Full copies waste time and storage, while direct writes to shared layers destroy image immutability and cross-container isolation. The constraint turns a convenient file operation into an identity or ordering bug.
Compose one view from different lifetimes
Think of each layer as a transparency sheet: lower sheets show through wherever upper sheets are blank. An overlay mount takes the image's layers as read-only lowerdirs (in manifest order), adds one empty writable upperdir, and exposes a merged view that the container mounts as /. Reads search top-down and return the first hit. Writes never touch the lowers — they land in the upper. Ten containers from one image share every read-only sheet and differ only in their thin upper layers.
Ordered read-only lower layers are merged with one container-private writable upper layer and presented as a single mount. 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.
flowchart TB
V["merged view — the container's /
(what the process sees)"]
U["upperdir (writable, per-container)
changed: /etc/app.conf"]
L3["lowerdir: app layer (RO)
/app/server"]
L2["lowerdir: runtime layer (RO)
/usr/bin/python"]
L1["lowerdir: base layer (RO)
/bin, /lib, /etc/app.conf"]
V --- U
U --- L3
L3 --- L2
L2 --- L1
style U fill:#fff8ec,stroke:#f2ddb0
It stacks immutable lower layers below a private upper layer and merged view. Its central claim is that container writes affect only the container's upper layer, never the shared image layers beneath it; the labels therefore describe authority rather than decorative grouping.
Copy only at the first write
The read path is the whole algorithm: check the upper, then each lower in order, first match wins. A file "modified" by the container exists twice — original in a lower, changed copy in the upper — and the upper always shadows:
Reads search the merged view; the first write to a lower-layer file copies it upward, and deletions are represented without changing the lower object. 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 traces a read from lower content and a first write through copy-up.
sequenceDiagram
participant P as Container process
participant O as Overlay driver
participant U as upperdir
participant L as lowerdirs (top → bottom)
P->>O: read /etc/app.conf
O->>U: exists here?
U-->>O: yes (container changed it)
O-->>P: upper copy — shadows the original
P->>O: read /usr/bin/python
O->>U: exists here?
U-->>O: no
O->>L: search layers top-down
L-->>O: found in runtime layer
O-->>P: read-only original, shared by all containers
It traces a read from lower content and a first write through copy-up. The ordering is valid only when it continues to preserve the stated invariant under retries and interruption.
Private writes must remain private
Two route workers modify the same apparent path, so each must observe its own result while the shared image remains unchanged. A partial or stale result must remain distinguishable from a complete image state; otherwise the cache or store begins to lie.
Container writes affect only the container's upper layer, never the shared image layers beneath it. The invariant is phrased in bytes, ownership, or completed prefixes so it remains true across storage implementations.
Mount MiniDock's frozen and living halves
MiniDock gains cheap writable instances by composing layers instead of cloning releases. MiniDock can adopt the content rule without preselecting the learner's attachment point.
What carries forward
- Container writes affect only the container's upper layer, never the shared image layers beneath it.
- Give containers independent writable views without copying or mutating shared image layers.
- The rejected shortcut remains a diagnostic: if the design starts depending on it again, the original constraint has probably been lost.
See what actually stuck.
Take the practice scenarios now.