Understanding Docker Vs Containerd

Written by - Ashwini Kanitkar
Reviewed by - Deepak Prasad

Getting started with containerd vs docker

As many of you know dockers have been a very powerful containerization tool that helps build, test and deploy applications in different environments seamlessly. It packages all the software dependencies into deployable containers which comprise the libraries, code, and runtime.

The core element here is the containers that are deployable across various environments which ease the application developments. In order to run these containers on the host system, we use containerd which is the container runtime of Docker.

In this article, let us, deep dive, into containerd and docker and understand the difference between them.


Understanding Docker Engine

The Docker engine is the core software that runs and manages containers. We often refer to it simply as Docker.

At the time of writing, the major components that make up the Docker engine are; the Docker daemon, containerd, runc, and various plugins such as networking and storage. Together, these create and run containers.

Understanding Docker Vs Containerd



As part of the effort to strip functionality out of the Docker daemon, all of the container execution logic was ripped out and refactored into a new tool called containerd (pronounced container-dee). Its sole purpose in life was to manage container lifecycle operations — start | stop | pause | rm....

containerd is available as a daemon for Linux and Windows, and Docker has been using it on Linux since the 1.11 release. In the Docker engine stack, containerd sits between the daemon and runc at the OCI layer.

One of the reasons for adding more functionality is to make it easier to use in other projects. For example, in projects like Kubernetes, it was beneficial for containerd to do additional things like push and pull images. For these reasons, containerd now does a lot more than simple container lifecycle management.


How containerd is related to docker?

Containerd is an open-source containerization platform that manages to create, start, stop and kill docker containers. It is helpful in all the operations that the user performs with the Docker CLI.

Understanding Docker Vs Containerd

Let us understand how this is used with an example.

Consider running an Nginx container with $docker run -p 80:80 -d nginxcommand.

When you run the above command, the docker asks the container runtime to pull the docker image and create a container from the Nginx image. Also, since the ports are exposed, it is also possible to connect to the web and host this application on the web.

In the backend, what happens is the containerd pulls the Nginx image from the dockerhub and creates a container out of it.

Let us define the workflow of this operation.

  1. When we run the command, initially the Docker CLI accepts the user command and passes it into the docker daemon which runs in the background of any docker process.
  2. Upon receiving the input, it further passes on instructions to containerd which is another process and it pulls the nginx docker image.
  3. Further containerd calls another application to perform operations which is called runc which is a low-level container runtime. In this case, it starts the nginx docker container.

In simple words, containerd is a high-level container runtime. It can be considered a container manager which

  • helps to download/upload the container images
  • establishes docker to docker communications by setting up the networks
  • start/stop/kill docker containers.

In a few cases, containerd asks another application to perform operations which is called runc which is a low-level container runtime.

Docker as a whole system comprises docker client, docker daemon, containerd, runc. This was considered to be the older way of docker and for a few years the docker developers separated out all these components to make the developer's life easy and to debug the issues. Sounds interesting, isn't it?

The new docker approach gives users the flexibility to choose and run the components that are required. This plug-and-play option has helped a lot of developer communities thereby making their application to be functional and consistent.

Previously, we saw what exactly happens when the user hits the docker command. So, now we know that with the new docker approach, we can eliminate docker CLI and docker daemon in our execution environment.

As a result of this, we can save a lot of our system’s memory. Hence, we can have a containerd and runc running in our system which will execute the user commands and complete the docker operations.

In a nutshell, containerd can still be used instead of docker as it can interact with low-level components which communicate with Operating System's Kernel inorder to spin off containers and perform in a way that docker does.


How to interact with containerd

There are several ways to interact with containerd using command-line interfaces like ctr, nerdctl and crictl

In case you have docker installed on your system, you will have containerd running by default. If you want to interact with the containerd, there is a utility called ctr which helps you do this.

Let us understand in detail with an example.

$ ctr


   ctr - 
  _____/ /______
 / ___/ __/ ___/
/ /__/ /_/ /

containerd CLI

   ctr [global options] command [command options] [arguments...]



ctr is an unsupported debug and administrative client for interacting
with the containerd daemon. Because it is unsupported, the commands,
options, and operations are not guaranteed to be backward compatible or
stable from release to release of the containerd project.

   plugins, plugin            provides information about containerd plugins
   version                    print the client and server versions
   containers, c, container   manage containers
   content                    manage content
   events, event              display containerd events

Consider pulling the Nginx docker image using the below command

$ sudo ctr images pull docker.io/library/nginx:latest

The ctr utility helps the user to interact with contained for debugging purposes. It will output the details of the steps and the status of the command execution as shown below.

docker.io/library/nginx:latest:                                                   resolved       |++++++++++++++++++++++++++++++++++++++| 
index-sha256:2f770d2fe27bc85f68fd7fe6a63900ef7076bc703022fe81b980377fe3d27b70:    done           |++++++++++++++++++++++++++++++++++++++| 
manifest-sha256:bab399017a659799204147065aab53838ca6f5aeed88cf7d329bc4fda1d2bac7: done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:8d634ce99fb933cae83bf1ebc98ca6a4bc683f632320ececee060ea84d2785fe:    done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:98b0bbcc0ec67f3b41dc3140ee2fe804d410548392307a2c6d4f9921ea30261f:    done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:bd159e379b3b1bc0134341e4ffdeab5f966ec422ae04818bb69ecef08a823b05:    done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:6ab6a6301bdeddbcd0e6193262b2c54740f4ea12640c81c951223cdd5ec842a3:    done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:fe24ce36f968b9315f7713fee767d50444dea2b59951f171054cb4e3c12d4b81:    done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:f5d8edcd47b1b04e279cc2414cad5c38b423d1d5ee9801ca7c81ef63d0941c98:    done           |++++++++++++++++++++++++++++++++++++++| 
config-sha256:51086ed63d8cba3a6a3d94ecd103e9638b4cb8533bb896caf2cda04fb79b862f:   done           |++++++++++++++++++++++++++++++++++++++| 
elapsed: 33.7s                                                                    total:  24.2 M (734.8 KiB/s)                                     
unpacking linux/amd64 sha256:2f770d2fe27bc85f68fd7fe6a63900ef7076bc703022fe81b980377fe3d27b70...
done: 9.916649937s



In this article, we have learned about the differences between docker and containerd. Container execution is handled by containerd. You can think of it as a container supervisor that handles container lifecycle operations. It is small and lightweight and can be used by other projects and third-party tools. For example, it’s becoming the most common container runtime in Kubernetes.

By default, Docker uses runc as its default container runtime. runc is the de facto implementation of the OCI runtime-spec and expects to start containers from OCI-compliant bundles. containerd talks to runc and ensures Docker images are presented to runc as OCI-compliant bundles.

In case you have any doubts, please feel free to add your questions in the comment section below and I shall try to respond at the earliest.

Happy learning!!





Ashwini Kanitkar

She brings many years of engineering experience in DevOps and Linux, specializing in CICD with Jenkins, AWS services, Docker, Kubernetes, and Terraform. She is also proficient in Shell and Python scripting. You can connect with her on <a href="https://www.facebook.com/golinuxcloud/" target="_blank" rel="nofollow noopener">Facebook</a> page.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

Leave a Comment