Cloud Native 12 min read

Mastering runc: Build and Run OCI Bundles from Scratch

This guide explains how runc implements the OCI runtime spec, walks through creating an OCI bundle, using skopeo and umoci to fetch images, and demonstrates running containers in foreground and detached modes while highlighting the underlying Linux namespace mechanics.

Ops Development Stories
Ops Development Stories
Ops Development Stories
Mastering runc: Build and Run OCI Bundles from Scratch

Original Container Runtime

runc is a command‑line client that runs applications packaged in the Open Container Initiative (OCI) format and is a reference implementation of the OCI runtime specification.

It works with OCI bundles, which consist of a root filesystem and a

config.json

file, not with Docker‑style images.

OCI bundles are simpler than full images; they lack layers, tags, registries, and other image‑specific features defined in a separate OCI image spec.

<code>OCI Image -> OCI Runtime Bundle -> OCI Runtime</code>

In practice this translates to:

<code>Container image -> Root filesystem and config.json -> runc</code>

To create a bundle, start with a

config.json

:

<code>mkdir my-bundle
cd my-bundle
runc spec</code>

The generated

config.json

contains a

process

section that defines the command to run inside the container, environment variables, and other settings.

<code>{
    "ociVersion": "1.0.1-dev",
    "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"]
    },
    "root": {"path": "rootfs", "readonly": true}
    ...
}</code>

Running the bundle without a proper root filesystem yields errors; you must provide a valid Linux rootfs. One way is to extract a busybox image:

<code>$ docker export $(docker create busybox) | tar -C /mycontainer/rootfs -xvf -</code>

How to Use skopeo and umoci to Get an OCI Application Bundle

Instead of building a rootfs from scratch, fetch a minimal image such as busybox using

skopeo

:

<code>yum install skopeo -y
skopeo copy docker://busybox:latest oci:busybox:latest</code>

Then unpack the OCI image into a bundle with

umoci

:

<code>umoci unpack --image busybox:latest bundle</code>

The resulting

bundle

directory contains

config.json

,

rootfs

, and metadata files.

According to the OCI runtime spec, the container expects certain filesystem mounts such as

/proc

,

/sys

,

/dev/pts

,

/dev/shm

, plus

/dev

and

/dev/mqueue

as required by runc.

Running an OCI Application Bundle with runc

Execute the bundle:

<code>runc run test</code>

This starts a shell inside the container, showing the typical Linux directory layout.

<code># runc run test
/ # ls
bin dev etc home proc root sys tmp usr var</code>

runc supports foreground and detached modes. In detached mode the container runs independently of the invoking shell:

<code>runc run test --detach</code>

Container state is stored on the host filesystem (e.g.,

/run/runc/TEST/state.json

), and the container’s process appears under PID 1 inside the namespace, while the host sees the runc process as its parent.

Linux namespaces (mount, UTS, IPC, PID, network) isolate the container, and runc manages these namespaces according to the OCI spec.

Shadow Ruler of the Container World

Tools like Docker, Podman, CRI‑O, and Kubernetes ultimately rely on runc to launch the container process. Understanding runc and the OCI runtime spec helps demystify container internals, even though most users interact with higher‑level tools.

Reference

[1] https://github.com/opencontainers/runtime-spec/blob/master/config.md

https://mkdev.me/en/posts/the-tool-that-really-runs-your-containers-deep-dive-into-runc-and-oci-specifications

https://github.com/opencontainers/runc/blob/master/docs/terminals.md

https://katacontainers.io/

https://polyverse.com/blog/skopeo-the-best-container-tool-you-need-to-know-about/

https://umo.ci/quick-start/workflow/

DockerruncLinux namespacescontainer runtimePodmanOCIskopeoumoci
Ops Development Stories
Written by

Ops Development Stories

Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.