Topic 9.3
The Runtime Stack: Docker, containerd, runc, OCI & CRI
In one line
docker run passes through several layers — the Docker daemon, containerd, a shim, and runc — all standardised by OCI specs; Kubernetes talks to containerd directly through the CRI.
Think of it like this
Ordering food through an app. You tap 'order' (docker CLI); the app's backend (dockerd) passes it to the restaurant manager (containerd), who hands a recipe card (OCI bundle) to a cook (runc). The cook makes the dish and leaves; a waiter (the shim) stays at the table in case anything's needed.
Key ideas
- 01
The layers: the docker CLI calls the Docker daemon (
dockerd) over its API; dockerd delegates to CONTAINERD (image pulls, storage, container lifecycle); containerd starts a SHIM per container, which calls RUNC to actually create the namespaces and cgroups and start the process, then exits. The shim stays as the container's parent, so containers survive daemon restarts. - 02
OCI (Open Container Initiative) standardises the IMAGE format (layers and manifest), the RUNTIME spec (the
config.jsonbundle runc executes), and the DISTRIBUTION API (how registries serve images). That's why images built by Docker run under Podman, containerd, CRI-O, or Kubernetes unchanged. - 03
Kubernetes removed dockershim in v1.24: the kubelet talks to containerd or CRI-O through the CRI (Container Runtime Interface), with no Docker daemon involved. Docker-built images still work, because they're OCI images.
crictlis the node-level debugging tool. - 04
Alternatives: Podman (daemonless, rootless-friendly, Docker-compatible CLI), BuildKit (the modern build engine behind
docker build), and Kaniko or Buildah (building images without a daemon, which is useful in CI: DevSecOps course, Lab 2.2).
Code & diagrams
docker info | grep -i -E 'runtime|containerd|cgroup'
ps -ef | grep -E 'containerd-shim|dockerd|containerd' | grep -v grep
sudo ctr -n moby containers list # containerd's view of Docker's containers
sudo crictl ps # on a Kubernetes node: containers via CRIExplain it without notes
Kubernetes stopped using Docker as its runtime. Why do images you build with docker build still run on Kubernetes?
Practice
If you restart the Docker daemon, do running containers stop? Why or why not?
Trade-offs
- ↔
Layered, standardised runtimes let tools be swapped (Docker, Podman, containerd, CRI-O) at the cost of more moving parts to understand when debugging at the node level.
Done when you can
I can trace
docker runthrough dockerd, containerd, the shim, and runc.I know what OCI standardises and what CRI is.
I can list containers with ctr and crictl.