containerd vs Docker vs CRI-O — Which Container Runtime Should You Use? (2026)
Kubernetes deprecated Docker as a runtime in 2020. In 2026, containerd and CRI-O run most production clusters. Here's the difference and which one to pick.
Docker was Kubernetes' original container runtime. In 2020, Kubernetes deprecated it. In 2026, most production clusters run containerd or CRI-O. Here's what changed, why, and which runtime to choose.
Why Kubernetes Dropped Docker
Kubernetes needs a runtime that implements the Container Runtime Interface (CRI) — a standard API for creating, running, and managing containers.
Docker was never built for CRI. Kubernetes used a shim called dockershim to bridge the gap. Maintaining dockershim was extra work, and it added latency.
Old (pre-1.24):
kubectl → API Server → kubelet → dockershim → Docker → containerd → container
New (1.24+):
kubectl → API Server → kubelet → CRI → containerd/CRI-O → container
Docker was removed from the middle. The actual containers still run the same OCI format — just without Docker in the path.
What's the CRI?
The Container Runtime Interface is a gRPC API that kubelet uses to:
- Create/delete containers
- Pull images
- Manage pod sandboxes
Any runtime implementing CRI works with Kubernetes. Today that's containerd, CRI-O, and (via plugins) others.
containerd
What it is
containerd started as Docker's internal component for container lifecycle management. Docker Inc. donated it to CNCF in 2017. It's now a standalone runtime.
Architecture
kubelet → CRI plugin → containerd → runc → container
containerd handles:
- Image pull and storage
- Container lifecycle (create, start, stop)
- Networking (via CNI plugins)
- Snapshotters for storage
Key facts
- Default runtime on EKS, GKE, AKS
- Written in Go
- Small footprint (~50MB)
- CRI plugin built-in (no extra shim)
- Supports both Docker and OCI images
Check if your node uses containerd
kubectl get node <node-name> -o jsonpath='{.status.nodeInfo.containerRuntimeVersion}'
# Output: containerd://1.7.xcontainerd CLI tool
# crictl — works with any CRI runtime
crictl ps # list containers
crictl images # list images
crictl logs <id> # container logs
crictl exec -it <id> /bin/sh # exec into containerCRI-O
What it is
CRI-O was built from scratch specifically for Kubernetes. Red Hat created it. The name comes from CRI + OCI (Open Container Initiative).
Architecture
kubelet → CRI-O → runc/kata/etc → container
CRI-O is minimal by design. It does exactly what Kubernetes needs — nothing more.
Key facts
- Default on OpenShift (Red Hat)
- Follows Kubernetes release cycle exactly (CRI-O 1.28 = K8s 1.28)
- Smaller than containerd
- No standalone Docker CLI compatibility
- Better suited for security-hardened environments
Check CRI-O
kubectl get node -o wide
# Look at CONTAINER-RUNTIME column: cri-o://1.28.xDocker (for development)
Docker still exists and is useful — just not as a Kubernetes runtime. In 2026:
- Docker Desktop — still the standard for local development on Mac/Windows
- Docker CLI — most engineers use it to build images and run containers locally
- Docker Compose — local multi-service dev environments
- docker build — building OCI-compatible images (usable by all runtimes)
The key insight: images built with docker build run on containerd, CRI-O, or any OCI-compliant runtime. The image format is standard.
Side-by-Side Comparison
| Feature | containerd | CRI-O | Docker (runtime) |
|---|---|---|---|
| CRI compliant | Yes | Yes | No (removed K8s 1.24) |
| Default on | EKS, GKE, AKS | OpenShift | Nowhere (K8s) |
| Image format | OCI + Docker | OCI + Docker | OCI + Docker |
| CLI tool | crictl, nerdctl | crictl | docker |
| Footprint | Small (~50MB) | Smallest | Large (~200MB+) |
| K8s support | All versions | All versions | ≤ K8s 1.23 |
| CNCF project | Yes (graduated) | Yes (incubating) | No |
| Release cycle | Independent | Tied to K8s | Independent |
| Security focus | Good | Excellent | Good |
| Windows support | Yes | No | Yes |
Performance
In practice, the performance difference is negligible for most workloads. Both CRI-O and containerd use runc as the low-level runtime (the thing actually creating the container process).
For very high pod churn (thousands of pod creates/deletes per minute), CRI-O has shown slightly better performance in benchmarks due to its simpler architecture.
Which Should You Use?
Use containerd if:
✅ You're using managed Kubernetes (EKS, GKE, AKS) — it's already set up
✅ You need Windows node support
✅ You want maximum ecosystem compatibility
✅ You're self-managing Kubernetes with kubeadm
Use CRI-O if:
✅ You're running OpenShift or RHEL-based nodes
✅ You need the tightest Kubernetes version pairing
✅ You have strict security requirements (CIS hardening)
✅ You want the minimal-footprint option
Use Docker (still) if:
✅ Local development on your laptop
✅ Building images in CI pipelines
✅ Running non-Kubernetes containers (docker run)
Migration: From dockershim to containerd
If you have old nodes still on Docker (K8s ≤ 1.23):
# 1. Drain the node
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
# 2. Install containerd
apt-get install containerd.io
containerd config default > /etc/containerd/config.toml
# Edit: SystemdCgroup = true
# 3. Update kubelet to use containerd
# /etc/default/kubelet or /var/lib/kubelet/kubeadm-flags.env
--container-runtime-endpoint=unix:///run/containerd/containerd.sock
# 4. Restart kubelet
systemctl restart kubelet containerd
# 5. Uncordon
kubectl uncordon <node>nerdctl — Docker-compatible CLI for containerd
If you miss docker commands on nodes running containerd:
# Install nerdctl
wget https://github.com/containerd/nerdctl/releases/latest/download/nerdctl-linux-amd64.tar.gz
tar xvf nerdctl-linux-amd64.tar.gz
mv nerdctl /usr/local/bin/
# Works just like docker
nerdctl build -t myapp:latest .
nerdctl run -d nginx
nerdctl ps
nerdctl imagesSummary
In 2026, containerd is the safe default for most teams. It's battle-tested on all major cloud providers, well-documented, and the most widely used. CRI-O is the right choice if you're on OpenShift or need the tightest security posture.
Docker is alive and well — just not as a Kubernetes runtime. You'll still build images with it every day.
Learn More
- CKA Exam on Udemy — Container runtimes are on the CKA curriculum
- KodeKloud Kubernetes Labs — Hands-on with crictl and containerd
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
Why Your Docker Container Keeps Restarting (and How to Fix It)
CrashLoopBackOff, OOMKilled, exit code 1, exit code 137 — Docker containers restart for specific, diagnosable reasons. Here is how to identify the exact cause and fix it in minutes.
Best DevOps Tools Every Engineer Should Know in 2026
A comprehensive guide to the essential DevOps tools for containers, CI/CD, infrastructure, monitoring, and security — curated for practicing engineers.
Docker Complete Beginners Guide — Everything You Need to Know
What is Docker, why engineers use it, and how to get started with containers from scratch. A practical, no-fluff guide.