Skip to content
Lesson 19 of 19

Step 1 of 5 · Reading · ~3 min

Read

Container Lifecycle

Putting It All Together

Every mechanism in this course is now something you have implemented rather than read about. This lesson is the assembly: what you built, what a real runtime has that you did not build, and where to go next.

What you built

MechanismWhat it isolates or limitsYour exercise
PID namespaceprocess numbering; who PID 1 isa per-namespace process table
Mount namespacethe filesystem viewper-namespace mount tables, copied on clone
Network namespaceinterfaces, addresses, routes, portsper-namespace device and route lists
User namespaceidentitya bidirectional uid map
UTS / IPC namespaceshostname; SysV and mqueue keyscopy-at-creation, and a per-namespace key space
veth + bridge + NATconnectivity between the abovethe routing decision: direct, NAT, or no route
cgroups: memory, cpu, pidshow much it may takebudgets, with OOM, throttling and EAGAIN
rootfs and pivot_rootwhat / meanspath resolution that cannot escape the root
layers, copy-on-write, OverlayFShow images are stored and sharedtopmost-wins lookup, copy-up, whiteouts, opaque dirs
OCI image and distributionhow images are named and shippedmanifest construction; the pull conversation
lifecycle, exec and attachhow you drive ita state machine, and namespace entry

Put those together and the sentence from lesson one is now literal rather than clever: a container is a process the kernel is lying to, on a budget, standing on a filesystem assembled from other people's tarballs.

What we glossed over

  • The OCI specifications. Two of them: the image spec (how images are built and distributed, which you touched) and the runtime spec (a config.json plus a rootfs directory — a "bundle" — and what a runtime must do with it). Docker, Podman, CRI-O and runc all comply, which is why images move between them.
  • containerd — the daemon that manages images, snapshots and lifecycle, sits above runc and below Docker, and is what Kubernetes actually talks to through the CRI.
  • Capabilities. Root is not one privilege but roughly forty: CAP_NET_ADMIN, CAP_SYS_ADMIN, CAP_NET_BIND_SERVICE and the rest. Docker drops most by default and --cap-add grants them back one at a time. This is what makes "root in a container" much weaker than root.
  • seccomp, AppArmor, SELinux — filters on which syscalls and which objects a process may touch at all. They sit on top of the isolation you built, not inside it, and they are what auditors ask about.
  • Rootless containers — the daemon and the container running as an unprivileged user, with the user namespace mapping container root to your own uid. Podman's default and Docker's rootless mode.

Why the capstone is a simulator

The same reason every exercise here is: the syscalls need capabilities a sandbox cannot grant. What the capstone does add is the thing none of the earlier exercises had — one object carrying several independent limits at once, which is what a container actually is.

Your exercise: End-to-End Runtime

RUN resolves an image, applies the flags it was given, and starts the container in one step. Memory and pids are separate accounts on the same container: an OOM must not touch the process count and an EAGAIN must not touch the memory charge. A flag that is absent means unlimited, which is not a large number — an unlimited account can never refuse anything. And the limits are enforced by the same rules you wrote two chapters ago: an over-limit ALLOC is refused and charges nothing, and FORK refuses at the ceiling rather than one past it.

STOP changes the state and nothing else. A stopped container still reports its usage and its limits, exactly as docker inspect does on a container that has exited — the accounting outlives the process, right up until the container is removed.

Finish this and you have written, in miniature, the thing under Docker, Podman and every Kubernetes node in the world.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…