New Docker Engine 1.11 integrates runC and containerd

Docker 1.11 is two week old now. Popular for its Software Infrastructure Plumbing(SIP), Docker Inc. first focused on adoption of libnetwork, followed by Notary and Unikernel Projects and now rightly integrated Docker Engine with runC and containerd. What it really means is the management of containers is now split up into a separate piece of infrastructure plumbing called containerd, a daemon for managing runC. With this new release, Docker Engine is now more loosely coupled to the containers.


This new architecture looks promising in the sense that it is expected to bring a significant performance boost when handling a big amount of containers. The new Docker Engine 1.11 execution layer will be entirely relying on well delimited tools that can be used independently, with the drawback that it won’t ship as a single binary anymore. It makes it possible to upgrade the daemon without shutting down all running containers in the future.As stated by Docker Inc., “..this new Engine architecture will use containerd for container supervision. Because containerd ultimately relies on runC and the OCI specification for container execution, this will open the door for the Engine to be able to use any OCI compliant runtime..”


Let’s have a quick look at Docker 1.11 new release components. I had a Ubuntu 14.04.3 system running on AWS cloud instance I tried downloading the latest release and tried looking into the release as shown below:

Downloading Docker 1.11:

root@ubuntu:~# cat /etc/issue
Ubuntu 14.04.3 LTS \n \l

root@ubuntu:~# wget–2016-04-23
Connecting to… connected.
Proxy request sent, awaiting response… 200 OK
Length: 20520756 (20M) [application/x-tar]
Saving to: ‘docker-1.11.0.tgz’

100%[======================================>] 20,520,756 329KB/s in 62s

2016-04-23 13:06:20 (325 KB/s) – ‘docker-1.11.0.tgz’ saved [20520756/20520756]

Checking docker version:

user@ubuntu:~$ sudo docker version
Version: 1.11.0
API version: 1.23
Go version: go1.5.4
Git commit: 4dc5990
Built: Wed Apr 13 19:36:04 2016
OS/Arch: linux/amd64

Version: 1.11.0
API version: 1.23
Go version: go1.5.4
Git commit: 4dc5990
Built: Wed Apr 13 19:36:04 2016
OS/Arch: linux/amd64


Extracting Docker 1.11:

root@ubuntu:~# tar xvzf docker-1.11.0.tgz

As shown above, a Linux docker installation is now made of 4 binaries (docker, docker-containerd, docker-containerd-shim and docker-runc). Here is a brief explanation in case you are completely new to runC.


runC is a lightweight universal runtime container. runC is built on libcontainer, the same container technology powering millions of Docker Engine installations.It is a CLI tool for spawning and running containers according to the OCP specification.The Open Container Project is an open governance structure for the express purpose of creating open industry standards around container formats and runtime. Projects associated to the Open Container Project can be found at

runc integrates well with existing process supervisors to provide a production container runtime environment for applications. It can be used with your existing process monitoring tools and the container will be spawned as a direct child of the process supervisor.

Containers are configured using bundles. A bundle for a container is a directory that includes a specification file named “config.json” and a root filesystem. The root filesystem contains the contents of the container.


Docker Inc. built up containerd as a seperate daemon to move the container supervision out of the core Docker Engine.It is firmly believed that Containerd improves on parallel container start times which means if you need to launch multiple containers as fast as possible you should see improvements with this release.Containerd is claimed to have full Support For starting OCI bundles And managing Their Lifecycle.

Containerd has full support for starting OCI bundles and mananaging their lifecycle. This allows users to replace the runC binary on their system with an alternate runtime and get the benefits of still using Docker’s API. When starting a container most of the time is spent within syscalls and system level operations. It does not make sense to launch all 100 containers concurrently since the majority of the startup time is mostly spent waiting on hardware / kernel to complete the operations. Containerd uses events to schedule container start requests and various other operations lock free. It has a configurable limit to how many containers it will start concurrently, by default we have it set at 10 workers. This allows you to make as many API requests as you want and containerd will start containers as fast as it can without totally overwhelming the system.

Let’s look at how the newly added docker-runc and docker-containerd looks like in this new release.

$sudo /usr/bin/docker-containerd -version
containerd version 0.1.0 commit: d2f03861c91edaafdcb3961461bf82ae83785ed7

Checking docker-containerd version:

$sudo /usr/bin/docker-containerd-ctr -v
ctr version 0.1.0 commit: d2f03861c91edaafdcb3961461bf82ae83785ed7

Checking docker-runc version:

$sudo docker-runc –version
runc version 0.0.9
commit: e87436998478d222be209707503c27f6f91be0c5
spec: 0.5.0-dev

Looking at the process states:

root@ubuntu:~# ps ax | grep docker
1091 pts/0 T 0:00 sudo docker daemon
1095 pts/0 T 0:00 sudo docker daemon
1107 ? Ssl 0:00 docker-containerd -l /var/run/docker/libcontainerd/docker-containerd.sock –runtime docker-runc

I have one Nagios container running as shown below:

userchef@ubuntu:~$ sudo docker-runc list
e938b4aeeed2484258aeb56f7ceb987f6226450c8c5bdc3c0261cedb1b49dd6e 3583 running /run/docker/libcontainerd/e938b4aeeed2484258aeb56f7ceb987f6226450c8c5bdc3c0261cedb1b49dd6e 2016-04-24T18:49:29.32912562Z

Normally, docker-runc needs 3 thing to start container:

  1. rootfs dir with the whole filesystem
  2. config.json
  3. runtime.json

We will create the rootfs, by exporting a docker container as shown below:

Exporting a container:

To be able to export a container, first you have to create one:

userchef@ubuntu:~$ sudo docker create –name container1 ajeetraina/testnagios shb64ed4ab4b872a6ff0f27825d4142e5f4c809aebe209591c56055f1d03a53a3b

Now you are ready to export it into a tar file: docker-nagios.tar

userchef@ubuntu:~$ sudo docker export container1 > docker-nagios.tar

To create the rootfs dir, just untar docker-nagios.tar into a directory named roots:

userchef@ubuntu:~$ sudo mkdir rootfs
userchef@ubuntu:~$ sudo tar -xf docker-nagios.tar -C rootfs/

userchef@ubuntu:~/rootfs$ ls
anaconda-post.log dev lib media opt run sys var
bin etc lib64 mnt proc sbin tmp
boot home lost+found root srv usr

Creating specification files:

With the Rootfs ready you need to generate 2 spec files. As shown below, the docker-runc can create a default file based on the rootfs directory using:

userchef@ubuntu:~$ sudo docker-runc spec
userchef@ubuntu:~$ ls
docker-nagios.tar rootfs
config.json myapp.tar shim-log.json

userchef@ubuntu:~$ sudo docker-runc start e938
sh-4.2# ls

Hence, we saw how to get started with docker-runc. In the next post, we will look more into containerd daemon in more detail.