Docker
There is no Docker engine magic. Every feature maps to a Linux primitive you already built by hand — this module makes each mapping explicit.
sudo apt install -y docker.io) and add yourself to the docker group, or prefix commands with sudo.Docker doesn't run a mini-VM. It runs an ordinary Linux process with its own namespaces.
Start a container and find its process — and its network namespace — on the host.
$ sudo ls -l /proc/$(docker inspect -f "{{.State.Pid}}" web)/ns/netThe container is a normal PID on your host with its own net namespace link. Exactly the unshare world you built in Linux.
Reveal solution
$ docker run -d --name web nginx $ docker inspect -f "{{.State.Pid}}" web $ sudo ls -l /proc/$(docker inspect -f "{{.State.Pid}}" web)/ns/net
An image is stacked read-only layers; the container adds a thin writable layer on top — via overlayfs (the storage abstraction from the Storage module).
Inspect an image's layers and see overlay mounts on the host.
$ mount | grep overlay | headYou'll see overlay mounts with lowerdir/upperdir — the layered rootfs, made real.
Reveal solution
$ docker image inspect nginx -f "{{.RootFS.Layers}}" $ mount | grep overlay | head
-p 8080:80 isn't magic routing — it's an iptables DNAT rule (the netfilter you met in Linux) rewriting the destination to the container.
Publish a port and find the DNAT rule it created.
$ sudo iptables -t nat -L DOCKER -n | grep 8080A DNAT rule maps host :8080 to the container's :80. That's the whole trick.
Reveal solution
$ docker run -d -p 8080:80 nginx $ sudo iptables -t nat -L DOCKER -n | grep 8080
Reach engineers who read the man page
Native, contextual, no tracking — this is how the curriculum stays free.
Docker's default network is a Linux bridge named docker0 — the same object you assembled by hand in the Linux module.
Look at docker0 and the container IPs on it.
$ ip addr show docker0docker0 has a subnet; each container gets an IP on it via a veth pair. Q3–Q6 of the Linux module, automated.
Reveal solution
$ ip addr show docker0 $ docker network inspect bridge -f "{{range .Containers}}{{.Name}} {{.IPv4Address}}{{end}}"
The app in a container is PID 1. If PID 1 exits, the container stops. A container with no long-running foreground process dies immediately.
Watch a container exit instantly, then make it stay up.
$ docker ps --filter name=stayupdocker run alpine exits at once (nothing to keep PID 1 alive). Give it a foreground process and it stays. This is the OS "app as PID 1" idea, biting.
Reveal solution
$ docker run --name gone alpine # exits immediately $ docker run -d --name stayup alpine sleep 1000 $ docker ps --filter name=stayup
Namespaces, cgroups, overlayfs, veth, DNAT — Docker is those five primitives with good ergonomics. Nothing you didn't already build by hand. Next: Kubernetes orchestrates thousands of these.