rgoussu@goussu: ~/library/platform/exercises
~/library/platform/exercises cat build-your-own-container-runtime.md

Build your own container runtime

# A run-a-process-in-a-box runtime built up from Linux primitives — namespaces, pivot_root, cgroups, layered images — until docker run holds no mystery.

Exercisesaved 2026-08-08source #exercise#containers#linux#platform

Goal

Write a small program (Go is the classic choice — Liz Rice's Containers from Scratch is the seed, and John Crickett's "Build Your Own Docker" challenge covers the same ground) that runs a command in its own container: isolated view, limited resources, its own root filesystem, eventually a real image pulled from a registry. It proves, in code you wrote, that a container is an ordinary Linux process wearing kernel features.

Subject: full brief & instructions

Practices

Milestones

  1. Isolate the viewmycontainer run <cmd> re-executes itself with new UTS and PID namespaces (clone flags), sets a hostname inside. Shippable: the hostname change is invisible outside; ps inside will still lie until milestone 2.
  2. A root of one's own — extract an Alpine rootfs, pivot_root (or chroot) into it, mount a fresh /proc. Shippable: the process sees itself as PID 1 in a clean filesystem and can't reach the host's.
  3. Limit the resources — create a cgroup v2 group, set memory and CPU limits, add the child to it. Shippable: a memory-hog inside gets OOM-killed at your limit while the host shrugs.
  4. Give it a network — a new network namespace wired to the host with a veth pair, addresses assigned, NAT out. Shippable: ping from inside the container reaches the internet.
  5. Real images — pull an image from a registry (OCI distribution API: manifest, then layers), unpack the layers in order — or assemble them with overlayfs for proper copy-on-write. Shippable: mycontainer run alpine sh with nothing pre-extracted.
  6. The UX — argument parsing, --mem/--cpu flags, exit-code propagation, cleanup on exit. Shippable: a colleague can use it without reading the source.

Stretch goals

  • Rootless mode with user namespaces — the hard mode that explains Podman's design.
  • mycontainer exec into a running container (enter its namespaces via setns).
  • Speak the OCI runtime spec (a config.json-driven create/start) and compare against runc.

Related