Docker105 min total · 19 parts
Docker Fundamentals: Images, Containers, and Writing a Good Dockerfile
Part 4 of 19 · ~2 min
The Docker Engine's Moving Parts
The word "Docker" actually names a small chain of separate programs handing work off to each other, and Marcus is about to learn that the hard way, roughly once a month, until he knows where the handoffs are:
- Docker CLI (
docker) — a thin messenger. Typing a command here doesn't do anything by itself; it packages up what you asked for and hands it off. - Docker daemon (
dockerd) — sits in the background (root, typically) and is where images actually get built and containers actually get started. - containerd —
dockerddoesn't manage a running container's lifecycle itself; it delegates that down to containerd, which Kubernetes also talks to directly on a containerd-based cluster. - runc — the layer that turns "start this container" into an actual namespaced, cgrouped process. Everything above it is coordination; this is where it becomes real.
So docker run isn't really one self-contained action — it's the first hop in a relay: the CLI hands the request to dockerd, dockerd hands it down to containerd, and containerd hands it down again to runc, which is the one that finally does the isolating. That relay is exactly why Marcus loses a container roughly once a month without touching his terminal: Docker Desktop pushes an update, restarts the daemon in the background, and every container he had running — including the worker container he'd started before a customer demo, on a Tuesday, for reasons that had nothing to do with the update — goes down with it. The containers are managed by a process that answers to the daemon, not to his terminal session, and the daemon doesn't check whether he was in the middle of something.
None of this is a design flaw so much as the intended shape of the thing — the same containerd that dockerd hands work off to is a standalone project other tools can drive directly, which is exactly how Kubernetes runs containers on a containerd-based node without going anywhere near the Docker CLI at all. The split between "the thing you type" and "the thing that actually does the work" is what makes that possible. It's also worth being able to answer, off the top of your head, which of the four pieces a given command actually touches — because a docker build failing with a permissions error and a docker run failing because a container won't start are, underneath, failures in two different places in that chain.