Skip to main content
You’ll frequently see both Docker and containerd in modern container ecosystems. Older docs often treat Docker as the default Kubernetes runtime, while newer guides reference containerd and CRI-compatible runtimes. You may also encounter multiple CLI tools — ctr, crictl, and nerdctl — which can be confusing. This article clarifies the history, key differences, and when to use each tool.

Early history and the rise of CRI

  • Docker (and a few alternatives like rkt) dominated early container adoption because Docker’s developer experience made containers easy to use.
  • Kubernetes was originally designed to orchestrate Docker, so the two were tightly coupled.
  • As Kubernetes evolved, the need to support multiple runtimes led to the Container Runtime Interface (CRI), allowing any CRI-compatible runtime to integrate with Kubernetes.

OCI (Open Container Initiative)

OCI defines two specifications that matter for runtime compatibility:
  • Image spec — how container images are built and stored.
  • Runtime spec — how a container runtime should behave.
Runtimes that adhere to OCI specs can be used by Kubernetes via the CRI, which decouples the orchestration layer from runtime implementations.

Dockershim and the decoupling

  • Docker predates CRI and was not originally built to implement it.
  • Kubernetes implemented dockershim — a compatibility layer — to keep supporting Docker while CRI was adopted.
  • Maintaining dockershim eventually became unnecessary overhead; Kubernetes removed dockershim in v1.24 and dropped direct support for Docker Engine as a node runtime.
  • Crucially: images built with Docker remain compatible because Docker follows the OCI image spec. Those images still run on CRI-compliant runtimes such as containerd.
A technical diagram showing container runtimes and their integration with Kubernetes — featuring logos and components for Docker (and dockershim), containerd, rkt, the Container Runtime Interface (CRI), and the Kubernetes wheel. The image maps connections between runtimes and Kubernetes with labeled blocks like CLI, API, imagespec, and runtimespec.

What is containerd?

  • containerd began inside Docker but is now a standalone, graduated CNCF project.
  • It implements container lifecycle operations and is CRI-compatible, so Kubernetes can use it directly without Docker.
  • Install containerd if you do not need Docker’s higher-level features (CLI, build tooling, volume/auth management, etc.).
Installing containerd (example extraction)

ctr — containerd’s low-level CLI

  • ctr is a low-level CLI bundled with containerd.
  • It’s primarily for debugging and low-level interactions; it exposes a narrower feature set than Docker.
  • For routine tasks, ctr is less user-friendly than higher-level tooling.
A presentation slide titled "CLI - ctr" with three bullet points: "ctr comes with containerD," "Not very user friendly," and "Only supports limited features." A small footer notes ctr is for debugging containerd and mentions the nerdctl tool as more user-friendly.
Basic ctr examples
ctr is intended for debugging and internal use. It is not recommended for general-purpose container management in production environments.

nerdctl — a Docker-like CLI for containerd

  • nerdctl provides a Docker-compatible CLI that talks to containerd.
  • It supports many Docker commands (including docker-compose in some setups) and adds modern features: encrypted images, lazy-pulling, P2P distribution, image signing/verifying, and Kubernetes namespaces.
  • For many workflows, replacing docker with nerdctl is straightforward.
A slide titled "CLI - nerdctl" listing that nerdctl provides a Docker-like CLI for containerd, supports docker-compose, and newer features such as encrypted container images, lazy pulling, P2P image distribution, image signing/verifying, and Kubernetes namespaces.
Docker → nerdctl command mappings

crictl — CLI for CRI-compatible runtimes

  • crictl is a kubelet-aware debugging and inspection tool maintained by the Kubernetes community.
  • It talks to the CRI endpoint and works across CRI-compatible runtimes (containerd, CRI-O, etc.).
  • Use crictl for inspecting or troubleshooting CRI-managed containers and pods; it’s not intended for general container lifecycle management outside Kubernetes because kubelet reconciles Pod state.
A slide titled "CLI - crictl" that explains crictl is a separate CLI used to inspect and debug CRI-compatible container runtimes. A diagram shows crictl between the Container Runtime Interface and runtimes like rkt and containerd, with a Kubernetes logo beneath.
Basic crictl examples
Note: crictl is kubelet-aware — containers created by crictl outside of a Pod may be removed by kubelet because kubelet reconciles the node state to match the Pods it manages.

Comparing Docker CLI and crictl

Many docker commands have equivalent crictl commands, but some options are unsupported or behave differently. Use crictl primarily for debugging and inspection. For a complete mapping and up-to-date differences, see the Kubernetes reference:

crictl runtime endpoints and the Kubernetes 1.24 change

Prior to Kubernetes v1.24, many clusters relied on dockershim and default CRI socket endpoints such as:
  • unix:///var/run/dockershim.sock
  • unix:///run/containerd/containerd.sock
  • unix:///run/crio/crio.sock
  • unix:///var/run/cri-dockerd.sock
With removal of dockershim in Kubernetes v1.24, cri-dockerd and associated endpoints changed. You should explicitly set the CRI endpoint for crictl when needed. Setting the runtime endpoint
These changes and rationale are discussed in the Kubernetes cri-tools repository:

Summary and recommendations

  • ctr: low-level containerd CLI for debugging. Use for deep troubleshooting of containerd internals.
  • nerdctl: Docker-compatible CLI for everyday container management on containerd. Best choice for replacing Docker CLI workflows.
  • crictl: Kubernetes community tool for inspecting and debugging CRI-compatible runtimes; kubelet-aware and intended for diagnostics.
  • containerd: a CRI-compatible runtime (formerly part of Docker, now a graduated CNCF project). Docker Engine is no longer a supported runtime in Kubernetes since v1.24, but Docker-built images remain compatible thanks to the OCI image spec.
A diagram comparing container runtimes and CLI tools, showing the containerd logo with "ctr" and "nerdctl" and the Kubernetes logo with the Container Runtime Interface and "crictl". A small table below lists Purpose, Community, and Works With for each tool (debugging, general purpose, ContainerD, Kubernetes, and CRI-compatible runtimes).
Quick tip: For day-to-day container work on nodes running containerd, prefer nerdctl for a Docker-like experience. Use crictl when troubleshooting CRI interactions with kubelet, and ctr only for low-level containerd debugging.

Watch Video