Runtimes Basics
This section gives you hands-on footing with the container runtime stack: what tools live on a node, how to inspect them, and where Docker fits versus where containerd takes over.
Search across all documentation pages
This section gives you hands-on footing with the container runtime stack: what tools live on a node, how to inspect them, and where Docker fits versus where containerd takes over.
crictl / ctr against containerd.kubectl configured against your cluster.# Quick check of the local Docker install (build/dev side)
docker version --format '{{.Server.Version}}'
docker buildx versionDocker's job is the developer inner loop: build and push OCI images.
docker build -t registry.example.com/app:1.0 .
docker push registry.example.com/app:1.0kubectl reports the container runtime per node.
kubectl get nodes -o wideCONTAINER-RUNTIME column - typically containerd://1.x or cri-o://1.x.crictl config) to use on the node.On a node, crictl is the CRI-native equivalent of docker ps.
crictl ps
crictl podscrictl ps lists application containers; crictl pods lists pod sandboxes.crictl talks to the same socket the kubelet uses, so you see the real state.crictl configured with the runtime endpoint, usually unix:///run/containerd/containerd.sock.kubectl is not enough and you need node-level truth.ctr is containerd's own low-level CLI, useful for debugging containerd itself.
ctr --namespace k8s.io containers list
ctr --namespace k8s.io images listk8s.io containerd namespace; you must pass it.ctr bypasses the CRI abstraction, so prefer crictl for pod-oriented work.ctr is not meant for production orchestration - it is a debugging tool.You can pre-pull images at the CRI layer to test registry connectivity.
crictl pull registry.example.com/app:1.0@sha256:...) in production for immutability.crictl logs reads the same logs the kubelet exposes.
crictl logs <container-id>crictl ps first.kubectl logs fails.crictl inspect <id> to see the full OCI config.Check which OCI runtime binary containerd invokes.
containerd config dump | grep -A3 'runtimes.runc'
which runcrunc; alternatives appear as extra handlers.runc --version confirms the version and the libseccomp it was built against.runsc or crun would be registered.RuntimeClass lets specific pods use a stronger isolation runtime.
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: gvisor
handler: runsc
---
apiVersion: v1
kind: Pod
metadata:
name: untrusted
spec:
runtimeClassName: gvisor
containers:
- name: app
image: registry.example.com/app@sha256:abc123...handler must be registered in the node's containerd config.runtimeClassName use the node default (runc).When a pod is stuck, drop to the node and inspect the sandbox lifecycle.
crictl pods --state NotReady
crictl inspectp <pod-id>
crictl stopp <pod-id> && crictl rmp <pod-id>inspectp shows the pod sandbox config, including its network namespace.kubectl afterward that state reconciled.Keep image building off your worker nodes entirely.
# CI runner (has Docker/BuildKit): build + push
docker buildx build --push -t registry.example.com/app:1.0 .
# Worker node (containerd only): kubelet pulls and runs it
kubectl run app --image=registry.example.com/app:1.0Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026