Tutorial: Explore Container Runtimes with Flatcar Container Linux
This tutorial is the second part of a series on Flatcar Container Linux, in which we will get familiar with the container runtimes. It also introduces the concept of running a custom version of containerd runtime as a systemd unit file.
Flatcar Linux instances can be launched in mainstream cloud platforms, including Amazon Web Services, Microsoft Azure, and Google Cloud. We will choose Equinix Metal, which gives us the flexibility to run the OS in the bare metal environment.
After signing up with Equinix Metal, we will launch a new on-demand server instance in the nearest supported region.

I chose the Singapore region, and the x1.small.x86 server configuration.
Next, give your instance a name, associate one of the registered SSH keys, and click on the deploy now button.

Within a few minutes, the server will be ready. You can track the progress in the sidebar of the console.
You can customize the instance by adding cloud-init data in YAML format.

Once the instance is ready, copy the IP address to SSH into it.

Exploring Docker Engine
Flatcar Container Linux supports all of the popular methods for running containers. We can choose to interact with the containers at a low-level, or use a higher-level orchestration engine, which is Kubernetes.
Every Flatcar Container Linux instance comes with a stable version of Docker CE and Docker CLI.

The Docker service gets started as soon as the Docker Socket is activated. You can find the systemd unit files, docker.service and docker.socket at /run/systemd/system directory.
If you want to run the Docker service all the time without having to wait for the socket activation, add the following to the user data. This configuration will help when you want to keep running containers with the restart attribute set to always.
systemd:
units:
- name: docker.socket
enabled: false
- name: docker.service
enabled: true
Exploring the containerd Runtime
Flatcar Container Linux comes with the containerd CRI plugin, and Dockershim enabled by default. Let’s explore that further by downloading the crictl CLI tool.
VERSION="v1.20.0" wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /opt/bin
We copied the binary to /opt/bin since /usr/bin is a part of the read-only filesystem.
Assuming Docker service is up and running, we can connect to the Dockershim endpoint through with crictl.
sudo crictl --runtime-endpoint=unix:///run/docker/libcontainerd/docker-containerd.sock version

Installing and Configuring a Custom containerd Runtime
It is possible to replace default Docker and containerd runtimes with custom versions. In this example, we will run containerd 1.4.1 instead of the default version, 1.4.3.
Let’s download the containerd 1.4.1 binary and move it to /opt/bin directory.
wget https://github.com/containerd/containerd/releases/download/v1.4.1/containerd-1.4.1-linux-amd64.tar.gz
tar xvf containerd-1.4.1-linux-amd64.tar.gz && sudo mv bin/containerd /opt/bin
We will create an empty file that will act as the placeholder for the configuration.
sudo mkdir -p /etc/containerd/ sudo touch /etc/containerd/config.toml
Create a systemd unit file with the below content. We are calling this containerd141.service to avoid the conflict with the current runtime configuration.
sudo bash -c 'cat << EOF > /etc/systemd/system/containerd141.service [Unit] Description=containerd container runtime After=network.target [Service] Environment=CONTAINERD_CONFIG=/etc/containerd/config.toml Environment=PATH=/opt/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin ExecStart= ExecStart=/opt/bin/containerd --config /etc/containerd/config.toml KillMode=process Restart=always LimitNOFILE=1048576 LimitNPROC=infinity LimitCORE=infinity TasksMax=infinity [Install] WantedBy=multi-user.target EOF'
Before activating this, let’s stop Docker and container containerd services.
sudo systemctl stop docker sudo systemctl stop containerd
Let’s activate the containerd 1.4.1 service.
sudo systemctl enable /etc/systemd/system/containerd141.service sudo systemctl start containerd141
We can now test the version of the runtime with the crictl tool.
sudo crictl --runtime-endpoint unix:///run/containerd/containerd.sock version
Notice that we are using the native socket of containerd instead of the Dockershim.

To initialize a custom version of containerd during the boot process, we can embed it in the Ignition file’s configuration, which we will explore in the next part of the series. Stay tuned.
Janakiram MSV’s Webinar series, “Machine Intelligence and Modern Infrastructure (MI2),” offers informative and insightful sessions covering cutting-edge technologies. Sign up for the upcoming MI2 webinar at http://mi2.live.
Feature image by Russ Ward on Unsplash.