Content

Docker vs. Containerd: The Ultimate Guide to Demystifying Containers

If you’re working with Kubernetes, you’ve probably heard the names Docker and Containerd. And if you’re like most people, you may have wondered: what’s the difference? Are they the same thing? Why did Kubernetes “drop” Docker?

This article will clarify all of that and give you a clear understanding of each piece of technology.

1. Docker: The Complete Platform

When we think of Docker, we think of the complete platform. It’s an all-in-one solution that popularized containerization. Docker includes everything a developer needs:

  • The CLI (Command Line Interface): The docker command-line tool we use to build, run, and manage containers.
  • The Docker Engine (Daemon): The background service that manages images, volumes, networks, and the container lifecycle.
  • The Container Runtime: The low-level engine that actually runs the container.

You can think of Docker as a complete car.

Image de car engine parts

. It’s ready to go as soon as you get in, with its engine, body, and all its features.

2. Containerd: The Low-Level Engine

Unlike Docker, Containerd is not a complete solution. It is a low-level container runtime. Its job is simple and precise: to manage the complete lifecycle of containers on an operating system. .

Containerd is responsible for:

  • Managing images (downloading, storing, etc.).
  • Creating and destroying containers.
  • Managing network connectivity for containers.

To use the car analogy again, Containerd is the car’s engine. It’s an essential building block, but it doesn’t allow you to drive. It’s designed to be used by other systems, like Docker or Kubernetes.

3. The CRI (Container Runtime Interface)

The CRI (Container Runtime Interface) is a key concept for Kubernetes. It is not a tool or a piece of software, but a standard API. .

Kubernetes is designed to be modular. To avoid being dependent on a single container runtime (like Docker), the Kubelet component needs a standard interface to interact with any runtime. The CRI is that interface.

Containerd was specifically designed to be CRI compliant. This is why Kubernetes was able to integrate directly with Containerd, making it more efficient and lightweight. This is also why many modern clusters no longer have Docker installed.

4. crictl: The Debugging Tool

If docker is the CLI for the Docker engine, then crictl is the CLI for the CRI. . It’s a troubleshooting tool that allows you to interact directly with the container runtime on a node, without going through kubectl or other high-level tools.

crictl is essential for cluster administrators because it allows them to view the status of containers and images independently.

A bridge to the runtime: the endpoint

To work, crictl needs to connect to the container runtime via an endpoint. This endpoint is usually a local UNIX socket. The path to this socket depends on the runtime you are using:

  • For Containerd: unix:///run/containerd/containerd.sock
  • For CRI-O: unix:///run/crio/crio.sock
  • For Docker (via cri-dockerd): unix:///var/run/cri-dockerd.sock

You can specify the endpoint directly in the command or set it as an environment variable to be used by default.

# Specify the endpoint for a single command
sudo crictl --runtime-endpoint unix:///run/containerd/containerd.sock ps

# Set the endpoint for all subsequent commands
export CONTAINER_RUNTIME_ENDPOINT=unix:///run/containerd/containerd.sock

crictl command examples

# List all pods managed by the CRI
sudo crictl pods

# List all running containers
sudo crictl ps

# List all container images on the node
sudo crictl images

5. Nerdctl: The Docker-like CLI

nerdctl is a CLI tool developed by the Containerd project. Its mission is to provide a user interface that mimics the Docker syntax (docker run, docker pull, etc.), but which interfaces directly with the Containerd runtime. . This allows users to easily switch from Docker to a Containerd-based environment without having to learn new commands like crictl, which is more focused on debugging.

To return to our analogy, nerdctl is like an adapter for your car’s steering wheel. It allows you to use your familiar steering wheel (Docker commands) to control the new engine (Containerd).

nerdctl command examples

One of the main advantages of nerdctl is its familiarity. The commands are nearly identical to those of Docker.

  • docker run becomes nerdctl run
  • docker pull becomes nerdctl pull
  • docker ps becomes nerdctl ps
  • docker images becomes nerdctl images

nerdctl is ideal for development or testing environments where you want to use familiar Docker commands to build and manage containers while benefiting from Containerd’s lightweight and performance.

In Summary

Feature Docker Containerd CRI crictl Nerdctl
Type Complete Platform Low-level Runtime Interface (Standard) CLI Tool CLI Tool
Purpose A-to-Z Management Container Execution Runtime Abstraction Runtime Debugging Familiar UX (Docker-style)
Analogy The Complete Car The Car’s Engine The Standard Steering Wheel The Mechanic The Steering Wheel Adapter
Used by K8s Indirectly Directly and Standard Standard Interface Runtime Debugging For Developers

In conclusion, the relationship is simple: Kubernetes uses the standard CRI interface to communicate with Containerd (the engine), which is responsible for running the containers. Docker, while popular, is a heavier platform that uses Containerd at its core. If something doesn’t work, crictl is the tool to look directly under the hood, and nerdctl is the tool for developers who prefer a familiar interface.