# containerd: the container runtime you embed, not the one you drive

> containerd is a CNCF graduated daemon for Linux and Windows that handles image transfer, storage, execution and supervision, and is designed to be embedded in a larger system rather than used directly by end users. Its Apache-2.0 licence and stable API make it infrastructure, not a developer tool.

**containerd/containerd** — An open and reliable container runtime

- Repository: https://github.com/containerd/containerd
- Website: https://containerd.io
- Stars: 21,359 · Forks: 4,138
- Language: Go
- License: Apache-2.0
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/containerd-containerd

## The problem containerd solves is not the one Docker solves

Docker bundles a daemon, a CLI, an image builder, a registry client and a developer experience into one product. containerd takes the runtime half of that and exposes it as a daemon that something else drives. The README describes it as managing the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments. That is a deliberately narrower scope than a developer tool.

The intended consumer is a larger system. The README states the project is designed to be embedded into a larger system, rather than being used directly by developers or end-users. Kubernetes is the obvious example, and the repository carries a k8s CI dashboard group with test results for running Kubernetes against main and release branches. If you are writing an orchestrator, a build service or a CI runner, containerd is the layer you call instead of shelling out to a container CLI.

Who it is not for: someone who wants to type a command and get a running container from a Dockerfile. There is a ctr binary in the repository, and it is useful for debugging, but the README points developers at the Getting Started example rather than presenting ctr as the primary interface.

## How containerd is put together: daemon, plugins, shims, snapshotters

The architecture image lives at docs/historical/design/architecture.png, and the repository layout confirms the shape. There is a core/ directory, a plugins/ directory, an api/ directory, and a client/ directory. The gRPC surface is versioned separately from the daemon: the recent releases list shows v2.4.0 for containerd itself alongside api/v1.12.0 for the API, and go.mod pins github.com/containerd/containerd/api v1.12.0 as a dependency. That split matters because an API release can move without forcing a daemon release.

Actual container execution is delegated. The README says most interactions with the Linux and Windows container feature sets are handled via runc and/or OS-specific libraries such as hcsshim for Microsoft. The required runc version is documented in docs/RUNC.md rather than in the README itself. go.mod shows github.com/containerd/go-runc v1.2.1 in the dependency set.

Storage is pluggable through snapshotters. The README names overlay as the default, notes btrfs as an alternative with a minimum recommended kernel of 3.18 that also needs the btrfs kernel module and btrfs tools installed, and go.mod carries github.com/containerd/btrfs/v2, github.com/containerd/zfs/v2 and github.com/erofs/go-erofs. Networking goes through CNI: go.mod pins github.com/containerd/go-cni v1.1.14 and github.com/containernetworking/plugins v1.9.1. Checkpoint and restore is a separate optional path requiring criu on the host.

## Installing containerd and running a first container with ctr

The README does not give a step-by-step install. It says to see the documentation on containerd.io, and points at docs/ops.md, docs/namespaces.md and docs/client-opts.md, with the hands-on example in docs/getting-started.md. It also notes that downloadable 64-bit Intel/AMD binaries of all official releases are on the releases page, that binaries are published for additional platforms, and that many Linux distributions package their own containerd, citing Canonical's Ubuntu packaging as an example. So there are two legitimate routes: a distribution package, or a release tarball. Which one you take depends on whether you want the distro's patch cadence or the upstream release.

If you build from source, the Makefile defines the install layout. PREFIX defaults to /usr/local, BINDIR to $(PREFIX)/bin, and the comment notes that files install under $(DESTDIR)/$(PREFIX), with the DESTDIR convention changing in containerd v1.6. The build requirements are in BUILDING.md.

Once the daemon is running, ctr is the client that ships in the repository. The README does not document ctr's full command set, so treat the following as the shape of the tool rather than a complete reference.

## Shell completion and the ctr client

Auto-completion is one of the few client behaviours the README documents in detail. It states that starting with containerd 1.4, the urfave client feature for auto-creation of bash and zsh autocompletion data is enabled. The documented way to use it in bash is to source the autocomplete file from the contrib directory, either from your shell profile or manually:

```bash
source ./contrib/autocomplete/ctr
```

The README does not describe what happens after sourcing beyond autocompletion being available. It also does not list the ctr subcommands, so anyone expecting a man-page-equivalent in the README will be disappointed. The ops documentation at docs/ops.md is where the README sends administrators, and namespaces in particular are worth reading before you touch a shared host, because containerd isolates images and containers by namespace and the default namespace used by ctr is not the one Kubernetes uses.

## Where containerd is the wrong choice

The most direct limitation is stated by the project itself: it is designed to be embedded into a larger system, rather than being used directly by developers or end-users. If your requirement is a single binary that builds an image from a Dockerfile and runs it, containerd does not offer that in the documented surface. You would be assembling the missing pieces yourself.

Platform support is not uniform. The README points to Platform Support in RELEASES.md for the full list of platforms and the level of support for each, which is an implicit acknowledgement that support differs by architecture and OS. Nightly builds exist for Linux and Windows from the main branch, and the README warns that nightly builds might have critical bugs, are not recommended for use in production, and come with no support. That is an honest statement, and it should stop anyone from pinning a nightly in a production node image.

Optional features carry host prerequisites that are easy to miss. Checkpoint and restore needs criu installed on the system. btrfs needs the kernel module and btrfs tools. The default overlay snapshotter uses features finalized in the 4.x kernel series, and the README suggests a minimum 4.x kernel as a reasonable starting point, with the caveat about distro kernel versioning. On an older distribution kernel, the default snapshotter may not be the right choice, and switching snapshotters is not a configuration detail you can defer until after the cluster is live.

## How containerd differs from Docker and from CRI-O

Docker and containerd are not competitors in the way the search results suggest. Docker's daemon uses containerd underneath, which is why the question of whether Docker still uses containerd keeps appearing. The practical difference is the surface area: Docker ships a developer-facing CLI, an image build system and a registry workflow; containerd ships a daemon and an API intended for another program to call. Choosing containerd means you or your platform supply the layer above it.

Podman takes a different architectural position again. It is a tool users run directly, and its documented model avoids a long-running central daemon, which is the opposite of containerd's design. If your reason for looking at containerd is that you want a daemonless, rootless, user-facing container command, Podman is closer to that description than containerd is.

CRI-O is the closest comparison in intent, because it exists to serve the Kubernetes Container Runtime Interface. containerd also implements CRI, and the repository's k8s CI dashboard group tracks Kubernetes health against containerd branches. The distinction is scope: CRI-O is built around the Kubernetes use case, while containerd presents itself as a general runtime daemon that Kubernetes happens to consume through a plugin. If Kubernetes is your only workload, both fit; if you also need the runtime for non-Kubernetes work on the same host, containerd's broader framing is the relevant difference.

## Maintenance, versioning and licence

The last push to the repository was on 2026-09-19, and the most recent release is containerd 2.4.0 from 2026-09-16, with api/v1.12.0 the same day and a 2.4.0-rc.0 three days earlier. That cadence, together with the separate API version stream, is the main upgrade consideration: you can move the daemon and the API independently, but go.mod pins the API module, so a Go client has to track it deliberately. RELEASES.md is the document the README defers to for versioning and stability of containerd components, and it is the right place to check before assuming a minor bump is behaviour-preserving.

Licensing is Apache-2.0, and the repository carries both LICENSE and NOTICE files. The Makefile header repeats the Apache 2.0 grant. Apache-2.0 includes an express patent grant and requires preservation of notices, which matters if you redistribute binaries. This is a description of the licence text, not legal advice; if you are embedding containerd in a product, have your own counsel read the NOTICE file and the vendored dependency licences under vendor/.

## Conclusion

Adopt containerd when you are building or operating a platform that needs a container runtime underneath it: Kubernetes nodes, CI fleets, or an internal orchestrator that talks to the API. Do not adopt it expecting a Docker-style developer workflow; the README says plainly that it is designed to be embedded rather than used directly by developers or end-users. Before committing, verify the runc version your release requires against docs/RUNC.md, confirm your kernel is at least 4.x if you intend to use the default overlay snapshotter, and check RELEASES.md for the support level of your platform rather than assuming parity across architectures.

## FAQ

### What is the difference between Docker and containerd?

Docker is a developer-facing product with a CLI, image build workflow and registry client, while containerd is a daemon that manages image transfer and storage, container execution and supervision, and low-level storage and network attachments. The README states containerd is designed to be embedded into a larger system rather than used directly by developers or end-users.

### Does Docker still use containerd?

The README does not describe Docker's internals, so it does not answer this directly. It does describe containerd as an industry-standard container runtime available as a daemon for Linux and Windows, which is consistent with it being consumed by other systems rather than only by end users. Anything beyond that would be outside what the repository documents.

### What is containerd in Kubernetes?

containerd is a container runtime daemon that Kubernetes can use to run containers on a node. The repository tracks this with a k8s CI dashboard group containing test results for Kubernetes run against main and a number of containerd release branches.

### What is containerd vs Podman?

The README does not compare the two, so the only defensible difference from this material is architectural: containerd is a daemon that a larger system embeds, while Podman is not described anywhere in the repository. Treat any deeper comparison as something to verify against Podman's own documentation.

### How do I install containerd?

The README does not give install steps. It directs readers to the documentation on containerd.io, notes that downloadable 64-bit Intel/AMD binaries of all official releases are on the releases page, and points out that many Linux distributions package their own containerd, citing Canonical's Ubuntu packaging as an example.

### How do I use containerd instead of Docker?

The README does not frame containerd as a Docker replacement. It says containerd is designed to be embedded into a larger system rather than used directly by developers or end-users, and points to docs/getting-started.md for anyone who wants to try it out.

## Sources

- [containerd/containerd on GitHub](https://github.com/containerd/containerd)
- [License: Apache-2.0](https://github.com/containerd/containerd/blob/main/LICENSE)
- [Project website](https://containerd.io)
- [README](https://github.com/containerd/containerd/blob/main/README.md)
- [Releases](https://github.com/containerd/containerd/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/containerd-containerd
