Minikube’s default container runtime is Docker, but you can switch it to containerd to see how Kubernetes behaves with a different low-level container manager.

Let’s spin up a Minikube cluster with containerd.

minikube start --container-runtime=containerd --driver=docker

This command tells Minikube to provision a Kubernetes cluster using the containerd runtime instead of the default Docker. The --driver=docker part is important because it means Minikube will use Docker as the virtualization layer to run the Kubernetes node itself, but inside that Docker container, Kubernetes will be configured to use containerd for managing application containers.

Once Minikube is up, you can verify the runtime:

kubectl get pods -n kube-system

Look for pods like kubelet and containerd. The kubelet is the Kubernetes node agent, and it’s configured to talk to containerd to start, stop, and manage your application containers.

Now, let’s deploy a simple application to see containerd in action.

apiVersion: v1
kind: Pod
metadata:
  name: nginx-containerd
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80

Apply this:

kubectl apply -f pod.yaml

And check its status:

kubectl get pod nginx-containerd

You should see it running. Behind the scenes, kubelet on your Minikube node is instructing containerd to pull the nginx:latest image and start a container from it.

You can even exec into the pod and see containerd’s fingerprints. First, find the container ID. You’ll need to SSH into your Minikube node:

minikube ssh

Once inside the Minikube VM, you can list containers managed by containerd:

sudo ctr containers ls

You’ll see an ID that corresponds to your Nginx pod. You can then use sudo ctr commands to interact with it directly, for example, sudo ctr tasks ps <container_id> to see processes running inside.

The primary benefit of using containerd over Docker as the container runtime in Kubernetes is its focus on being a lean, robust, and standards-compliant container runtime. It abstracts away the complexities of Docker’s daemon and provides a more direct interface for Kubernetes. This can lead to improved performance and stability, especially in large-scale deployments. containerd is also the runtime used by Google Kubernetes Engine (GKE) and is a CNCF graduated project, making it a widely adopted and supported choice.

When you switch runtimes, it’s not just about containerd versus Docker. It’s about how Kubernetes interacts with the underlying container primitives. containerd uses the Open Container Initiative (OCI) runtime specification. This means it can work with various low-level runtimes like runc (the default) or crun. kubelet communicates with containerd via gRPC, and containerd then uses its own internal APIs to manage container lifecycles, images, and storage.

One of the most subtle differences you’ll encounter is how image management is handled. While both Docker and containerd pull images, containerd’s image store is more integrated with its own management APIs. You won’t find a docker images equivalent directly accessible from outside the Minikube VM in the same way. Instead, you’d use sudo ctr images ls inside the VM. This separation of concerns means containerd can be more efficient for Kubernetes itself, as it doesn’t need to go through the Docker daemon’s API for every image operation.

If you ever need to switch back to Docker, you’d simply restart Minikube without the --container-runtime flag, or explicitly specify it:

minikube delete
minikube start --container-runtime=docker --driver=docker

This would revert your cluster to using the Docker daemon for container management.

The next step after getting comfortable with different runtimes is understanding how network plugins integrate with Kubernetes and the chosen container runtime.

Want structured learning?

Take the full Minikube course →