Feedback

Chat Icon

Painless Docker - 2nd Edition

A Comprehensive Guide to Mastering Docker and its Ecosystem

Hack the Container: Understanding Docker's Inner Workings
12%

A Deep Dive into Container Prototyping with runC

runC is what makes Docker containers possible at the most fundamental level. The goal of this section is to provide a hands-on experience with this low-level tool to continue understanding how containers work under the hood.

Start by installing Docker on your Linux machine - this will also install runC:

# exit the current namespace if you are still in it
exit

# Install Docker (we will use v29.1.5)
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh --version 29.1.5

# Start Docker service
systemctl start docker

Let's create a directory (/tmp/mycontainer) where we are going to export the contents of the image Busybox. The goal is to extract the filesystem of a Docker image and use it as the root filesystem (rootfs) for a container managed by runC (we create our image manually from scratch, but for simplicity, we use a pre-built image here).

Busybox, if you're new to it, is a lightweight Linux distribution that provides a minimal set of Unix utilities in a single executable file. It's often used in embedded systems and containerized environments due to its small size and efficiency.

# Change to root user
sudo su

# Create the directory
mkdir -p /tmp/mycontainer

# Create a rootfs directory
mkdir -p /tmp/mycontainer/rootfs

# Export the Busybox image filesystem to the rootfs directory
cd /tmp/mycontainer && \
    docker export $(docker create busybox) | tar -C rootfs -xvf -

# Finally, list the content of the rootfs directory
ls -l rootfs

Create a spec file (config.json) that will be used by runC to run the container:

# cd into the container directory
cd /tmp/mycontainer

# Create the runc JSON spec file
runc spec

ℹ️ The spec file is a JSON file that contains the configuration of the container. It contains the rootfs path, the hostname, the mounts, the namespaces, the process, and more.

The runc spec command initially created a config.json file with default settings. You can open and inspect this file using any text editor or by running:

jq . config.json

You should see an output similar to the following (truncated for brevity):

{
 "ociVersion": "1.2.1",
 "process": {
  "terminal": true,
  "user": {
   "uid": 0,
   "gid": 0
  },
  "args": [
   "sh"
  ],
  "env": [
   "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
   "TERM=xterm"
  ],
  "cwd": "/",
  "capabilities": {
   "bounding": [
    "CAP_AUDIT_WRITE",
    "CAP_KILL",
    "CAP_NET_BIND_SERVICE"
   ],
   "effective": [

Painless Docker - 2nd Edition

A Comprehensive Guide to Mastering Docker and its Ecosystem

Enroll now to unlock all content and receive all future updates for free.

Unlock now  $31.99$25.59

Hurry! This limited time offer ends in:

To redeem this offer, copy the coupon code below and apply it at checkout:

Learn More