Take your first steps with containerd and run your docker images as usual
In December 2020, the Kubernetes project has deprecated docker. Through this lecture, we are going to have a first look at the
dockerhistory to understand the reasons for this deprecation. This will bring us next to discover
containerdand figure out its advantages.
We will practice
containerd by installing it on a Raspberry Pi. This target platform is a good scenario to dig into the different components needed to use
containerd. There are no available binaries so we will build them from the sources. Once installed, we will see how to interact with it using
ctrcommand and what there is possible to do.
The Docker Software History
Docker software was created in 2013 and contributed to making containerization famous and accessible. However, people are often confusing
docker and containerization.
Docker ≠ containers
The containerization in Linux was possible with these two Linux kernel features:
- Linux kernel namespace defines the boundaries of a process awareness of what else is running around it.
- Control groups (cgroups) are a kernel feature that manages and isolates the resources (CPU, memory) affected by a process.
Linux Containers (LXC) was released in 2008 and relies on both previous kernel features. It provides an API to easily create and manage container application systems.
In its beginning,
dockerwas using the LXC stack to isolate application resources. The
dockerprowess was to create a standard software unit where the user can define images and launch them easily in containers.
Software architecture evolution
Based on LXC,
dockerwas really dependent on its development. To remediate that,
dockerstarted to implement libcontainers to launch containers without LXC.
In parallel at that time, there were many criticisms made against the monolithic architecture of
dockercontaining the CLI and the daemon. Having taken into account these feedbacks
docker started cutting out the daemon and the CLI in
In 2015 the Open Container Initiative (OCI) was founded to create an application container standard. Docker company has been a major key player in its definition. Two standards emerged from this initiative which constitutes the OCI model :
- runtime-spec defining how to run a container :
- image-spec defining the image creation :
Docker company donated
libcontainersto the OCI. It is now a part of the runc project which is the OCI runtime. Nowadays,
dockeris no longer the monolithic block it once was. It uses
runcto manage the run of the containers :
containerdwas born out of
dockerand was included from the 1.11 release :
It is a runtime implementing the Container Runtime Interface (CRI) and presents interesting assets for hosted systems :
“containerd is an industry-standard container runtime with an emphasis on simplicity, robustness and portability. It is available as a daemon for Linux and Windows, which can manage the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments, etc.” From https://github.com/containerd/containerd
Docker and Kubernetes
Before the 1.20 release,
dockerto communicate with the containers.
dockeritself calls containerd to manage the containers :
dockerin favor of runtimes using the Container Runtime Interface (CRI) such as
cri-o. You will receive warnings if you still use
dockerin this release. The change will be effective in the v1.22 release. The previous diagram looks like that now:
In spite of this
kuberneteschange, you can continue to use Docker in your CI/CD or for development purposes.
dockerbrings a lot of user-experience features to make the interaction easier. Nevertheless, a container orchestrator like
kubernetesneeds only a container runtime to manage containers. Dealing with an extra layer can bring more complexity that does not create more value.
Containerd on a Raspberry Pi
I use a Raspberry Pi with armv6l processor architecture and Raspbian OS. You should check your processor architecture using
uname and adapt the source code to your architecture.
We ensure the system is up-to-date:
$ sudo apt update $ sudo apt full-upgrade $ sudo rpi-update
We need some build tools to compile sources :
$ sudo apt install autoconf automake libtool curl unzip gcc make
We also need a recent
golangversion installed :
$ wget https://golang.org/dl/go1.15.8.linux-armv6l.tar.gz $ sudo tar -C /usr/local -xzf go1.15.8.linux-armv6l.tar.gz $ echo 'PATH="$PATH:/usr/local/go/bin"' | tee -a $HOME/.profile $ echo "export GOPATH=$(go env GOPATH)" | tee -a $HOME/.profile $ source $HOME/.profile $ go version # version should be 1.15.8
libseccomp packages for seccomp support:
$ sudo apt install libseccomp2 libseccomp-dev
$ go get -v github.com/opencontainers/runc $ cd $GOPATH/src/github.com/opencontainers/runc $ make -j`nproc` $ sudo env PATH="$PATH" make install
btrfspackages to prepare
sudo apt install btrfs-progs libbtrfs-dev
protobufsources and build them:
$ wget https://github.com/protocolbuffers/protobuf/archive/v3.14.0.tar.gz -O protobuf_v3.14.0.tar.gz $ tar xzf protobuf_v3.14.0.tar.gz $ cd protobuf-3.14.0/ $ ./autogen.sh $ ./configure $ make -j`nproc` $ make -l2 -j`nproc` check $ sudo make install
containerdsources and build them:
$ go get -v github.com/containerd/containerd $ cd $GOPATH/src/github.com/containerd/containerd $ make -j`nproc` $ sudo env PATH="$PATH" make install
containerd build is finished we can check the binary:
$ containerd --version containerd github.com/containerd/containerd v1.5.0-beta.1 cfa842c278694860a7e32917066f4a24978f80d0
We deploy the provided
systemdservice file to run
containerdas a daemon:
cd $GOPATH/src/github.com/containerd/containerd sudo cp containerd.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable containerd.service sudo systemctl start containerd.service
Interact with containerd
We are going to use
ctr command to interact with
containerd. It was included in the
NAME: ctr - __ _____/ /______ / ___/ __/ ___/ / /__/ /_/ / \___/\__/_/ containerd CLI USAGE: ctr [global options] command [command options] [arguments...] VERSION: v1.5.0-beta.1 DESCRIPTION: 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. COMMANDS: 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 images, image, i manage images leases manage leases namespaces, namespace, ns manage namespaces pprof provide golang pprof outputs for containerd run run a container snapshots, snapshot manage snapshots tasks, t, task manage tasks install install a new package oci OCI tools shim interact with a shim directly help, h Shows a list of commands or help for one command GLOBAL OPTIONS: --debug enable debug output in logs --address value, -a value address for containerd's GRPC server (default: "/run/containerd/containerd.sock") [$CONTAINERD_ADDRESS] --timeout value total timeout for ctr commands (default: 0s) --connect-timeout value timeout for connecting to containerd (default: 0s) --namespace value, -n value namespace to use with commands (default: "default") [$CONTAINERD_NAMESPACE] --help, -h show help --version, -v print the version
containerd can pull images from a container registry and it supports tags. We use
ctrto pull the
$ sudo ctr image pull docker.io/library/nginx:latest
ctr we can have the list of images. We can ensure the
nginx image has been pulled:
$ sudo ctr image ls $ sudo ctr image ls -q docker.io/library/nginx:latest
We have the
nginximage and we can now run a container using it:
$ sudo ctr container create docker.io/library/nginx:latest webdemo
Is the container running? Let’s confirm it by listing the containers:
$ sudo ctr container list CONTAINER IMAGE RUNTIME webdemo docker.io/library/nginx:latest io.containerd.runc.v2
If we delete the image the container is still running :
$ sudo ctr image remove docker.io/library/nginx:latest docker.io/library/nginx:latest $ sudo ctr image ls -q $ sudo ctr container list CONTAINER IMAGE RUNTIME webdemo docker.io/library/nginx:latest io.containerd.runc.v2
Now we can remove the container :
sudo ctr container delete webdemo
We had an overview of
dockerhistory. We have seen it was monolithic software in the beginning. Docker has contributed to defining container standards in the OCI. Resulting in that,
docker architecture has changed.
dockerbut decided in the 1.20 release to deprecate it. We have seen that
runcto run containers. Its added value is to provide a great user-experience to manage images and resources for developers.
In the case of a distributed system like
kubernetes, it can directly call the container runtime. An extra layer is not needed and can create complexity and more calls across the software layers.
Finally, we practiced
containerdby installing and configuring it on a Raspberry Pi. It is a good target to test
containerdbecause it has limited resources and most of the time you don’t build images on it. You just want to pull images and run them into containers. We have observed we can pull
dockerimages and launch containers as usual with