Container Runtimes and runC Training - Hands-on Lab

Container Runtimes and runC

To know about the building blocks for containers and container runtimes

27 January 2022

Nowadays containers are becoming the default choice to deploy applications. Containers are created using Containers Runtimes like Containerd, cri-o, Docker, etc. We run our applications in an isolated environment such that applications have their own independent identity like hostname, IP Address, etc. In this hands-on lab, we are going to explore Container Runtimes. 

In Operating Systems like Linux and Windows, we have features like Cgroups and Namespaces; which enable containerization. 

Figure 1: OS Features
Figure 1: OS Features


  • Control Groups (cgroups) provide a mechanism to organize processes hierarchically and impose limits on how much resources they can use. 
  • Cgroups are used for resource allocation like the container is going to have 1 CPU and 2 GB of RAM. 
  • In simple terms, think of Cgroups as something which defines “how much to use”.


  • Namespaces allow us to create isolated environments for the containers like the container is going to have its IP address and its hostname.
  • This creates an illusion of a process running in the namespace that they have the resources all by themselves.
  • Namespaces allow us to abstract global system resources such as network interfaces (net) or mount points (mnt). 
  • In simple terms, think of NameSpaces as something which defines “what to use”.
  • In Linux, we have six namespaces which are:
Figure 2: Different Namespaces in Linux
Figure 2: Different Namespaces in Linux

Container Runtimes

Namespaces and Cgroups both have been in existence for a long time and they are being related to containers because these features of Linux Kernels helps to create containers which is not an easy process. Hence, Container Runtimes act as the middleware software to save us and facilitate the easy creation of containers. They use these complex kernel features to create ready-to-deploy containers which can be easily understood by the diagram below

Figure 3: Container Creation
Figure 3: Container Creation

The container runtime is responsible for:

  • Consuming the container mount point provided by the Container Engine
  • Consuming the container metadata provided by the Container Engine
  • Communicating with the kernel to start containerized processes

As we know, container runtimes use OS features but to avoid vendor locking and other companies from making their container runtime, a group of IT companies came together and formed an open governance structure, called The Open Container Initiative, under The Linux Foundation.

Open Container Initiative (OCI) and runC

The governance body came up with specifications to create standards on the Operating System processes and application containers. When OCI was created, Docker donated the libcontainer code and turned it into a standalone utility called runC. Now, runC is the reference implementation and used by other Container Engines.

  • runC is the CLI tool for spawning and running containers according to these specifications.    
  • runC has a very short utility and expects a mount point (directory) and meta-data (config.json) to be provided to it. 
  • runC also helps in running applications packaged according to the Open Container Initiative (OCI) format and compliant with the Open Container Initiative specification.

Implementation of runC

To install runC on the system use the apt install runc command

apt update
apt install runc -y 
  • To check runC is installed on the system using runc command
  • Now to run the container with runC, we need an image. So for this, we will be using debootstrap, which is a tool that will install a Debian-based system into a subdirectory of another, already-installed system through the sudo apt install debootstrap command
sudo apt install debootstrap -y
  • Then create a new /mnt/chroot-ubuntu-trusty directory 
sudo mkdir /mnt/
sudo mkdir /mnt/chroot-ubuntu-trusty
  • Then with the help of debootstrap, install a Ubuntu distribution in the new directory created earlier with the following command.
cd /mnt/chroot-ubuntu-trusty
sudo debootstrap trusty /mnt/chroot-ubuntu-trusty
  • Now go to the /mnt/ directory we created earlier.
cd /mnt/
  • As we got the image now make a sample spec to run the containers using the runc spec command
runc spec

After running this, we will get a config.json file in the current directory along with chroot-ubuntu-trusty directory, which helps to create the container which can be seen through the ls command.

  • This config.json file has the information about configurations to run the containers like oci version, os architecture, etc.
  • Edit the config.json file through nano/vim editor, currently in the ‘root’ section ‘path’ has a value of ‘rootfs’ which indicates the image location but here we have the image in the ‘chroot-ubuntu-trusty’ location.
  • Replace the ‘rootfs’ with ‘chroot-ubuntu-trusty’
  • Then run a container with runc command
runc run myc

Here myc is the name of the container and you can give any other name also of your choice. runC will find the config.json file and it will create the container with myc name which will run a shell program in it and open a shell for us and we can come out of this container through exit command.

Figure 4: Shell in myc container
Figure 4: Shell in myc container
  • In the config.json file, we can also change the ‘args’ to ‘date’ which is currently ‘sh’ to get the current date when the container runs. 
  • On saving the changes and running the container again, it shows the current date instead of the shell program.
runc run myc
Figure 5: current date in myc container
Figure 5: current date in myc container


In this hands-on lab, we have seen the building blocks of containers and learned about container runtimes with OCI specification and implemented runc.

How likely are you going to recommend this lab to your friends or colleagues?


Leave a comment:

About the Author

Oshi Gupta

Oshi Gupta

DevOps Engineer & Technical Writer, CloudYuga

Oshi Gupta works as a DevOps Engineer and Technical Writer at CloudYuga Technologies. She is a CKA certified and has been selected for LFX mentorship in Spring 2022 for CNCF Kyverno. She loves writing blogs and is keen to learn about various cloud-native technologies. Besides this, she loves cooking, badminton, traveling, and yoga.