For years "Docker" was synonymous with "containers". But the actual architecture underneath has changed. containerd[1] is today the standard container runtime in Kubernetes and other platforms, and Docker (the daemon) is just one of the layers wrapping it. nerdctl[2] offers an alternative: the familiar Docker CLI but talking directly to containerd.

Key takeaways

  • containerd is the standard K8s runtime since dockershim was removed in 2022; Docker Engine is no longer in the middle.

  • nerdctl is a Docker-compatible CLI that talks to containerd directly, developed by the official team.

  • Advantages over Docker Engine: rootless by default, encrypted images with ocicrypt, lazy-pulling, and native CNI.

  • Docker Engine still wins on tool ecosystem, advanced Compose, and Swarm.

  • nerdctl fits best in environments already running containerd (k3s, K8s nodes) and where rootless is a requirement.

How we got here

Until 2020, Kubernetes ran containers through Docker Engine. In 2020 they announced dockershim deprecation (the shim translating K8s requests to Docker), and in 2022 they removed it. Since then, the standard K8s runtime is containerd directly, no Docker Engine in between.

containerd has existed since 2014 as a Docker subproject, then donated to the CNCF. It’s smaller and more specialised: only manages container and image lifecycle. No build, UI, Swarm networking, or the other layers Docker Engine added.

The problem: if the container engine = containerd, what do you use on the command line? crictl is too low-level (designed for Kubernetes, not humans). That’s where nerdctl comes in.

What nerdctl is

nerdctl is a Docker-compatible CLI: day-to-day commands are identical (nerdctl run, nerdctl ps, nerdctl build) and it talks to containerd directly. The containerd team itself develops and officially distributes it.

Features it includes that Docker Engine doesn’t natively:

  • Rootless support by default. Runs containerd and its containers as unprivileged user with no extra setup.

  • Encrypted and signed images. Integration with ocicrypt[3] and cosign[4] for secure supply chain, directly relevant to the supply-chain requirements in NIS2.

  • Lazy-pulling. With stargz-snapshotter[5], starts containers before downloading the whole image, useful for large images.

  • Native CNI support. Networks configure with standard CNI plugins, the same Kubernetes uses. Reuses your knowledge.

When switching makes sense

Three scenarios where nerdctl beats Docker Engine:

  • Development on machines already running containerd. If your local environment has k3s or Docker Desktop using containerd internally, nerdctl removes the Docker Engine layer. Less memory, fewer processes.

  • Consistency with K8s production. If your production cluster uses containerd, developing with the same runtime avoids subtle surprises (storage-driver differences, network handling, cgroups). See Kubernetes 1.28 and native sidecars to understand what’s in the containerd layer.

  • Restricted environments. Rootless containerd + nerdctl works where Docker Engine doesn’t: hosts where you can’t grant root privileges.

Cases where Docker Engine still wins

Areas where Docker still leads:

  • Tool ecosystem. IDEs, plugins, Docker Desktop extensions: all assume Docker Engine. nerdctl covers almost every command but not every integration.

  • Docker Compose. nerdctl has nerdctl compose but trails compose v3.8+ compatibility and advanced features (profiles, extensions).

  • Docker Swarm. If you use Swarm as orchestrator, there’s no alternative: nerdctl doesn’t implement Swarm mode.

  • Team learning curve. If the whole team knows Docker, switching just for "better technology" rarely pays the transition cost.

Installation and first steps

On a Linux with containerd already installed (via apt/yum or as part of a K8s node):

# Download binary (latest release)
wget https://github.com/containerd/nerdctl/releases/latest/download/nerdctl-full-linux-amd64.tar.gz
tar -xzf nerdctl-full-linux-amd64.tar.gz -C /usr/local/

# First container
nerdctl run --rm hello-world

# List images
nerdctl images

# Run detached
nerdctl run -d -p 8080:80 nginx

The syntax is familiar for anyone coming from Docker. For rootless use:

containerd-rootless-setuptool.sh install
systemctl --user start containerd
nerdctl run --rm hello-world   # now runs as your user, no sudo

nerdctl vs podman

podman[6] is another Docker CLI alternative, particularly popular in Red Hat environments. Key differences with nerdctl:

  • Runtime: podman uses crun/runc directly, no containerd. nerdctl uses containerd.

  • Daemon: podman is daemonless (each command spawns containers with no persistent process). nerdctl requires containerd running.

  • Kubernetes: podman can generate K8s manifests (podman generate kube). nerdctl doesn’t.

For teams already running K8s, nerdctl fits better: it reuses the runtime that is already installed. For RHEL teams with more independent flows, podman is the natural choice.

Conclusion

nerdctl represents the maturation of the container stack: clean separation between runtime (containerd), CLI (nerdctl), and orchestrator (K8s). For development environments wanting to align with K8s production, or where rootless is a requirement, the transition pays. For workflows where Docker Engine works well there’s no urgency, but knowing the alternative is worthwhile.

Frequently asked questions

Can I use nerdctl with my Docker Compose files?

Partially. There is nerdctl compose, but it trails Docker in compose v3.8+ compatibility and in advanced features such as profiles or extensions. There is also no alternative for Docker Swarm: nerdctl does not implement Swarm mode. On the other hand, the basic commands are identical to Docker (nerdctl run, nerdctl ps, nerdctl build), so the syntax feels familiar from day one.

How do I run nerdctl rootless without sudo?

With containerd already installed, run containerd-rootless-setuptool.sh install and then systemctl --user start containerd; from there nerdctl run --rm hello-world runs as your user, no sudo. Rootless support comes by default with no extra setup, which lets you work on hosts where you cannot grant root privileges, where Docker Engine does not work.

What is the difference between nerdctl and podman?

podman uses crun/runc directly without containerd and is daemonless, each command spawns containers with no persistent process, whereas nerdctl requires containerd running. podman can generate Kubernetes manifests with podman generate kube; nerdctl cannot. For teams already running K8s, nerdctl fits better because it reuses the runtime that is already installed; for RHEL teams with more independent flows, podman is the natural choice.

Sources

  1. containerd
  2. nerdctl
  3. ocicrypt
  4. cosign
  5. stargz-snapshotter
  6. podman