Guided Problem
MiniDock Build 02: Isolate ParcelFlow Workloads
- Time
- 20m
- Level
- foundation
- Artifacts
- not specified
Namespaces: The Walls
Design claim: A container is a host process whose kernel-visible world is assembled from several independent namespaces.
Starting model
- You can assign launch and lifecycle responsibilities so running containers survive daemon and runtime-tool exits.
- The useful vocabulary at this point is deliberately small: namespace, PID, mount, UTS.
Isolation is plural
Workloads on one host need private process, filesystem, hostname, IPC, user, and network views without booting separate kernels. Begin with the guarantee visible to a workload or operator. Kernel machinery matters only after a simpler arrangement can no longer supply that guarantee.
The tempting shortcut is straightforward: use a changed root directory as the entire isolation boundary. The shortcut is plausible on a quiet development host, where its missing boundary has not yet been tested. A filesystem boundary does not hide host processes, network interfaces, hostnames, IPC objects, or user identities. The constraint reveals which responsibility must move before the design can survive isolation or process failure.
Build a world from independent views
The kernel doesn't have a single "isolate this process" switch. Instead it offers one namespace type per global resource, and the runtime opts into each. The six that matter: PID (process gets its own process tree, sees itself as PID 1), MNT (its own mount table, hence its own filesystem root), NET (its own network interfaces, IPs, ports), UTS (its own hostname), IPC (its own shared-memory world), and USER (its own user IDs — root inside can be nobody outside). Because they're independent, you can mix walls: two containers can share a NET namespace while keeping separate PID trees — that's exactly how Kubernetes pods work.
Linux namespaces virtualize individual resource views and can be composed or deliberately shared one namespace at a time. The named mechanism is the consequence of that separation: one layer owns policy, another enforces it, and callers receive a stable promise.
Read the topology as a map of authority. Durable knowledge, transient setup, and kernel enforcement should not blur into one box.
flowchart LR
P["container process
(sees itself as PID 1)"]
PID["PID ns
private process tree"]
MNT["MNT ns
private mount table / rootfs"]
NET["NET ns
private interfaces + ports"]
UTS["UTS ns
private hostname"]
IPC["IPC ns
private shared memory"]
USR["USER ns
private UID mapping"]
P --- PID
P --- MNT
P --- NET
P --- UTS
P --- IPC
P --- USR
It places one process inside separate PID, mount, UTS, network, IPC, and user views. Its central claim is that namespace sharing is explicit per resource; sharing one view does not imply sharing the others; the labels therefore describe authority rather than decorative grouping.
Join only what the workload is allowed to see
Ordering matters: every namespace is created and furnished before the application process replaces the runtime's child via exec. From the app's first instruction, the lie is already complete — it has never seen the real host.
The runtime creates or joins the requested namespaces, mounts the root filesystem inside the mount view, and executes the process within the assembled set. Trace the order carefully; each step establishes a fact the next step is entitled to use.
The second figure tests the same model in motion: it orders namespace setup before mounting and process execution.
sequenceDiagram
participant R as OCI runtime
participant K as Kernel
participant A as App process
R->>K: clone child with new PID, MNT, NET, UTS, IPC, USER ns
K-->>R: child exists inside fresh namespaces
R->>K: furnish: mount rootfs, set hostname, map UIDs
R->>A: exec the application
note over A: first instruction runs —
the app has only ever seen the fake world
It orders namespace setup before mounting and process execution. The ordering is valid only when it continues to preserve the stated invariant under retries and interruption.
One shared wall must not collapse the room
A debugging container intentionally joins a target network namespace but must not inherit its process or mount view. A sound boundary either preserves its promise or refuses the operation where the promise becomes impossible.
Namespace sharing is explicit per resource; sharing one view does not imply sharing the others. This rule survives changes in implementation names because it describes ownership rather than a particular process tree.
Compose MiniDock's isolation set
MiniDock must build isolation as a set of selectable walls rather than one opaque container flag. MiniDock needs the property now, but its learner must still decide where the responsibility belongs.
What carries forward
- Namespace sharing is explicit per resource; sharing one view does not imply sharing the others.
- Isolate container resource views while sharing only an explicitly selected namespace.
- 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.