← Blog/Engineering/Oct 18, 2026 · New

Kubernetes Stopped Using Docker in 2022. Almost Nobody Noticed.

Omenabyte Intelligence·Oct 18, 2026·9 min read
Typographic cover reading Kubernetes stopped using Docker, with a faint 1.24 watermark and coral accent

One seat at the port. Two brands on the crate.

The version of this you learn first is clean and it fits on a whiteboard. Docker is the shipping container: it packs your app, its runtime, your libraries and your settings into one box, and that box runs the same on a laptop, a server, or a cloud instance. Kubernetes is the port: it manages those boxes across many machines, keeps the number you asked for actually running, and when a box breaks or a crane falls over, it puts a replacement somewhere healthy.

Docker builds. Kubernetes runs. Package it once, orchestrate it forever.

That model is genuinely useful and I am not here to talk you out of it. It is how I explain the two to people myself. The thing worth knowing is that it describes a division of *products*, and the thing your cluster actually runs on is a division of *interfaces*. Those two have not lined up since May 2022, and the way they came apart explains something general about infrastructure that outlives this particular example.

The part of the model that is exactly right

Kubernetes does not build your containers. There is no kubectl build. You write a Dockerfile, something turns it into an image, and Kubernetes schedules that image. Nothing in the Kubernetes control plane knows how a layer was produced or whether a build cache was involved.

The other direction is just as true. Docker does not schedule your fleet. Run docker run on ten machines and you have ten independent containers with no shared opinion about how many should exist. Nobody replaces anything when one dies. That is not a gap in Docker, it is out of scope for the tool.

And the reconciliation half of the model is accurate down to the mechanics. A ReplicaSet exists to hold a stable set of Pods running. The Kubernetes documentation is explicit that it replaces Pods "deleted or terminated for any reason, such as in the case of node failure or disruptive node maintenance." Crash, dead node, kernel upgrade: it does not distinguish. It compares what you asked for against what exists and moves the second number toward the first.

So the teaching split survives contact with the mechanism. What it does not survive is contact with what is actually installed on your nodes.

What happened in 2022

In release 1.24, Kubernetes removed a component called dockershim. The container runtime documentation states it plainly: dockershim "has been removed from the Kubernetes project as of release 1.24."

Which means that for a while now, a standard Kubernetes cluster has not been using Docker to run your containers. It has been using containerd or CRI-O. That is the current requirement, not a roadmap item. Recent Kubernetes releases require a runtime that conforms to the Container Runtime Interface, and Docker does not. That gap is the entire reason the shim existed.

Here is the part I find genuinely funny. Ask someone how their cluster runs containers and Docker is a very common answer. Ask them to check and they usually find containerd. Which raises the obvious question: if the runtime underneath everyone's cluster was swapped out, why did almost no one have to change anything?

Why the swap was invisible

Two stacks side by side. Before v1.24 the Kubernetes control plane reaches containerd through an adapter box labelled dockershim, shown struck through. Since v1.24 the same control plane reaches containerd directly through an arrow labelled CRI, with no adapter.
Both columns are the same cluster doing the same work. The only difference is that the adapter in the middle of the left column was removed, and the arrow underneath it got shorter. Diagram: Omenabyte Intelligence.

Because the name "Docker" was never one program. The Kubernetes project's own explanation is that Docker "isn't actually one thing, it's an entire tech stack," and one layer inside that stack is containerd, a container runtime in its own right.

The layer Kubernetes could not use

Picture the stack from the outside in. At the very top there is the CLI you type at, the daemon you talk to over a socket, the build cache, the Compose files, the desktop app. Below that sits containerd, which does the actual work of pulling images and running processes. The top layers are what make Docker pleasant. They are also exactly the layers Kubernetes cannot use, for a reason that is easy to miss: Kubernetes is not a human. All that developer ergonomics exists for a person at a terminal, and a scheduler is not a person at a terminal.

So Kubernetes had to reach past the pleasant part to get at the useful part, using a translation layer, dockershim. That translation layer was code the Kubernetes project had to maintain purely so it could talk to a runtime whose friendly exterior was in the way. Eventually someone looked at that arrangement and asked the reasonable question of why they were maintaining a shim to get at containerd when they could just talk to containerd.

Removing dockershim did not remove Docker from anyone's cluster. It removed the adaptor. The thing on the other side of the adaptor was already containerd, and it stayed.

What actually lasted

The image. Specifically, the OCI image.

When you run docker build, what comes out is an image under the Open Container Initiative specification, not a Docker-specific artifact, and that specification is the reason containerd and CRI-O can pull an image Docker produced and run it without Docker being involved anywhere. Kubernetes slated Docker for deprecation in 2020 and the announcement still had to include a line reassuring people that images built with docker build would keep working, because the image format was never Docker's to take away.

Sit with the shape of that for a second. The product was replaced. The artifact stayed. The command stayed. What did not stay was the assumption that the product and the artifact were the same thing.

A timeline from 2015 to 2026 with three bands. Your Dockerfile and the OCI image specification run unbroken across the whole period. The runtime band changes at May 2022, from dockerd plus dockershim to containerd or CRI-O.
Two of the three bands never changed. The third was replaced under them, at a point most people running the cluster never noticed. Diagram: Omenabyte Intelligence.

The one caveat that keeps Docker in the picture

Docker Engine does still appear on the supported runtime list, which surprises people who read that Docker was removed. It is there through cri-dockerd, a CRI adaptor maintained outside the Kubernetes project. So you can run Docker as your Kubernetes runtime today. It is simply no longer the path Kubernetes owns, and no longer the default you get by accident.

Where the "runs the same everywhere" promise bends

The video's own wording is that the container "runs the exact same way on any machine. Your laptop, a server, the cloud. It doesn't matter." That is true in the way that matters and misleading in the way that costs people an afternoon.

Docker's own documentation describes what a container is built from: several features of the Linux kernel, with namespaces providing the isolated workspace. That is the mechanism, and it has a consequence people skip. A container is not a small virtual machine. It is a process group on a shared kernel. The kernel is the host's.

The kernel has to match

Follow that through and the promise becomes conditional. A Linux container needs a Linux kernel underneath. This is why Docker Desktop on Windows and macOS runs a virtual machine. The container is not running on your laptop's kernel, it is running on a Linux kernel inside a VM on your laptop. The abstraction holds, and the mechanism is doing real work you did not ask about.

The architecture has to match

Architecture is the other half. An amd64 image does not run on arm64 unless something is emulating or a multi-architecture manifest is picking the right layers for you. This is why the same image "just works" on your M-series laptop and your x86 server until the day the manifest is missing.

Neither of these breaks the model. They define its boundary. "Runs the same everywhere" is really "runs the same userland on any matching kernel and architecture," which is still an enormous improvement over what came before and is not the sentence on the poster.

Capacity was never the dividing line

The other simplification is that Docker is for one machine and Kubernetes is for many.

Kubernetes runs perfectly well on a single node. k3s, kind and minikube will all put a real control plane on one box, and the reconciliation loop does not care how many machines it is reconciling across. On one node it still compares desired against actual and still replaces what died. You lose the part where a dead node's work moves elsewhere, because there is no elsewhere. That is a resilience property, not the definition of orchestration.

Docker, meanwhile, ships its own orchestrator. Swarm is not where I would point you in 2026, but its existence is the point: orchestration was never a capability Docker lacked. Docker had a different opinion about how to do it and lost the argument.

So the honest dividing line is not scale, it is who owns the loop that decides what should exist and makes the world match. Kubernetes will do that on one machine. Docker Swarm did it across many. The metaphor describes the common case, not the boundary.

What to check on your own cluster

If your answer to "how does my cluster run containers" is Docker, it is worth ten seconds to find out.

# what is the runtime actually installed on each node
kubectl get nodes -o wide

# read the container runtime straight off the node
kubectl get node <node-name> -o jsonpath='{.status.nodeInfo.containerRuntimeVersion}'

If that comes back with containerd:// or cri-o://, your cluster stopped using Docker years ago and everything kept working, which is the whole story in one line of output.

What actually breaks

For most people none of this matters, and the correct move is to close the terminal and get on with your day. It matters if you rely on the Docker socket inside the cluster, because /var/run/docker.sock is a Docker-specific interface and it goes away with the runtime. That pattern, often called Docker-in-Docker, is what actually broke for people in 1.24 and why the migration guides talk about kaniko, buildah and similar tools rather than about Docker generally.

The bit worth keeping

The metaphor the video opens with is good and I would keep it. Docker is the crate; Kubernetes is the port. The correction is smaller and stranger than "Docker is dead," which it is not, and the Kubernetes project said so at the time.

The port authority stopped buying that brand of crate in 2022 and the crates still fit, because the thing that got standardised was the shape of the crate, not the company that made it.

Interfaces outlive implementations. It is why a runtime swap that touched every cluster in the world was a non-event, and it is worth noticing the next time you are picking between two products that look equivalent on today's feature list. The one whose interface other people implement tends to be the one still standing when the products have turned over twice.

The framing here comes from a two-minute explainer by Virex Explains (facebook.com/share/v/1LpcffW2r5/), which is accurate about what Kubernetes does. It does not mention the runtime change; the mechanism and every document quoted above are from the Kubernetes and Docker documentation.

Container platforms

Know which layer you actually depend on.

We audit container platforms for the dependencies that look permanent and are not: runtime interfaces, image supply chains, and the vendor-specific hooks your deployment quietly relies on.

Source & credits

The shipping-container and port framing, and the laptop-to-cloud promise examined in the middle of this piece, are from a two-minute explainer byVirex Explains, which is accurate about what Kubernetes does and does not mention the runtime change. The mechanism is from theKubernetes container runtimes documentation, the project'sDocker deprecation notice, theDocker overviewand theReplicaSet documentation. Both diagrams were drawn for this article. No endorsement by any project or person named here is implied.

Originally published on omenabyte.com → https://omenabyte.com/blog/kubernetes-stopped-using-docker