runc
The reference OCI runtime: a small Linux command-line tool that turns a bundle into a running container, and the default runtime underneath containerd and Docker Engine.
Linux Foundation project- What it is
- Containers
- Type
- Open source
- Made by
- Open Container Initiative (Linux Foundation), donated by Docker
- Foundation
- The Linux Foundation, joined June 2015. Part of the Open Container Initiative
- License
- Apache 2.0
- Facts checked
- 28 October 2026
What it is
runc does one job: given an OCI bundle, a directory with a root filesystem and a config.json, it creates the container the configuration describes and runs its process. It sets up Linux namespaces, cgroups (v1 or v2, directly or through systemd), mounts, capabilities, seccomp filters and AppArmor or SELinux labels, then starts the program and gets out of the way. Its commands follow the OCI Runtime Specification’s lifecycle: runc create builds the container without starting the program, runc start runs it, and runc kill, runc delete and runc state follow; runc run does create and start in one go. It also runs rootless containers as an ordinary user and checkpoints and restores running containers with CRIU. It is written mostly in Go, runs only on Linux, and its own README says it is “a low level tool not designed with an end user in mind”: it does not pull images, set up networks or keep logs.
Those jobs belong to the engines above it. Docker Engine hands containers to containerd, and containerd, the most common runtime behind Kubernetes nodes, uses runc by default through its io.containerd.runc.v2 shim. CRI-O switched its default to crun, a runtime written in C, in version 1.31 (September 2024), and Podman picks crun first when both are installed. Since runc 1.3 (April 2025) a new minor release comes about every six months, with published end-of-support dates: 1.5.0 arrived in June 2026 and 1.5.2 in September, 1.6.0 is due at the end of October 2026, and support for 1.3 ends the same month. Because every container on a host is started by the same runc binary with host privileges, its security record matters: high-severity container escapes were fixed in 2019, 2021, 2024 and three at once in November 2025, and runc can now be built with libpathrs, a Rust library for safe path handling.
Why teams pick it
- The reference implementation of the OCI Runtime Specification, and the default runtime in containerd and so in Docker Engine and many Kubernetes nodes: the most widely exercised Linux container runtime
- Covers the Linux container feature set: cgroup v2 and the systemd cgroup driver, rootless containers, seccomp, AppArmor and SELinux, and checkpoint/restore with CRIU
- Predictable releases since 2025: a minor version about every six months, with published support windows for older branches
- Signed releases and an independent security audit by Cure53
Watch out for
- Containers share the host kernel and runc runs with host privileges, so a runc or kernel bug can mean an escape; for untrusted code, gVisor or Kata Containers add a second boundary
- Only the lowest layer: no image pulling, networking, logging or restart policies, so you almost always use it through containerd, Docker, CRI-O or Podman
- Linux only, and written in Go, which the CRI-O maintainers cite when choosing crun for faster starts and lower memory use
- Older branches drop off quickly under the six-month cadence: the 1.2 branch and earlier are already unsupported, and 1.3 support ends in October 2026
Alternatives
What all containers have in common →Compare side by side →
gVisorOpen sourceA Linux kernel reimplemented in Go that runs in user space, so a container’s system calls never reach the host kernel directly.
Kata ContainersOpen sourceA container runtime that starts each pod inside its own lightweight VM, so Kubernetes and Docker keep working but every pod gets its own kernel.
AWS FargateAWSRuns ECS tasks and EKS pods without servers: you size each task, AWS finds the machine.How it fits with other technologies
Run a container with runc alone, from its README (needs root, or `runc spec --rootless`) · bash
mkdir -p /mycontainer/rootfs && cd /mycontainer
# fill the root filesystem, here by exporting busybox from Docker
docker export $(docker create busybox) | tar -C rootfs -xvf -
runc spec # writes a template config.json for the bundle
runc run mycontainerid # create + start, attached to the terminal
# or step by step, as an engine does
runc create mycontainerid && runc start mycontainerid
runc list
runc kill mycontainerid KILL && runc delete mycontaineridNotable container escapes fixed in runc#
All high severity. Each one let code inside a container, or a malicious image, reach the host.
| CVE | Published | What it allowed |
|---|---|---|
| CVE-2019-5736 | February 2019 | A container running as root could overwrite the host’s runc binary through /proc/self/exe and gain root on the host; affected runc up to 1.0-rc6 and Docker before 18.09.2 |
| CVE-2021-30465 | May 2021 | Swapping a mount destination for a symlink at the right moment put mounts outside the container’s root filesystem |
| CVE-2024-21626 | January 2024 | A leaked file descriptor gave a new process a working directory on the host filesystem, through runc exec or a malicious image |
| CVE-2025-31133, -52565, -52881 | November 2025 | Mount races around masked paths and /dev/console, and redirected writes to procfs, allowed escapes and denial of service |
See it in a real stack
No architecture uses runc yet. Drop it into the playground and wire it up yourself.Open playground →Where it came from2014–2026
Docker first started containers with LXC. In Docker 0.9, on March 10, 2014, it made its own library the default: libcontainer, a Go library that called the kernel’s container features directly, which the team said “drastically reduces the number of moving parts” and protected Docker from differences between LXC versions and distributions.
On June 22, 2015, when Docker, CoreOS and others announced the Open Container Project, Docker donated a command-line wrapper around libcontainer as runC, with all the “plumbing” Docker used to talk to the kernel, to be the reference implementation of a common runtime standard. libcontainer moved into the runc repository. The first 1.0 release candidate came in June 2016, but runc 1.0.0 only shipped on June 22, 2021, after a long run of release candidates.
Over the same years runc became the layer nearly every Linux container engine called. The CVE-2019-5736 escape in February 2019 showed what that meant: one bug exposed Docker, Kubernetes and other platforms at once. Minor releases stayed irregular (1.1 in January 2022, 1.2 in October 2024) until the maintainers adopted a six-month cadence with published support windows, starting with 1.3 in April 2025.
Why it’s built this way
- Call the kernel directly instead of going through LXC
- LXC behaved differently across versions and distributions. A Go library managing namespaces, cgroups, capabilities and AppArmor itself removed that dependency and the bugs that came with it.
- A separate binary started per container
- Engines start runc to set up a container and let it exit, so the engine can be upgraded or restarted without touching running containers, and any OCI-compatible runtime can replace runc.
- Reference implementation of an open specification
- Donating the runtime to the OCI and tying it to the Runtime Specification let other runtimes, such as crun, youki, gVisor and Kata Containers, accept the same bundles, so engines aren’t bound to one implementation.
Timeline
- 2014
Docker 0.9 makes libcontainer its default instead of LXC (March 10)
- 2015
Docker donates runC to the new Open Container Project (June 22)
- 2019
CVE-2019-5736: a container can overwrite the host’s runc binary (February)
- 2021
runc 1.0.0 released (June 22)
- 2024
CRI-O makes crun its default instead of runc (1.31, September)
- 2025
runc 1.3 starts a six-month release cadence (April); three escapes fixed (November)
- 2026
runc 1.5.0 (June); 1.6.0-rc.1 (October 6)
- Docker blog: Docker 0.9, introducing execution drivers and libcontainer (March 10, 2014)
- Docker blog: Introducing runC (June 22, 2015)
- OCI: About the Open Container Initiative (Docker donates its format and runtime, runC)
- GitHub: opencontainers/runc releases (v1.0.0-rc1 in June 2016 to v1.6.0-rc.1)
- CVE-2019-5736 record (CVE Program)
- CNCF blog: What’s new in CRI-O 1.31 (crun becomes the default)
- GitHub: runc v1.5.0 release notes (support policy status, 1.6.0 due late October 2026)
Sources14 · facts checked 28 October 2026
- GitHub: opencontainers/runc README (Linux only, low-level tool, OCI bundles, rootless, build tags)
- GitHub: opencontainers/runc RELEASES.md (six-month cadence and support policy)
- GitHub: runc v1.5.0 release notes (June 2026; 1.2 unsupported, 1.3 until end of October 2026; libpathrs)
- GitHub: opencontainers/runc releases (v1.3.0 April 2025, v1.4.0 November 2025, v1.5.2 September 2026, v1.6.0-rc.1 October 2026)
- GitHub: opencontainers/runc security advisories
- CVE-2019-5736 record (overwrite the host runc binary via /proc/self/exe)
- CVE-2024-21626 record (leaked file descriptors, host working directory)
- GitHub: opencontainers/runtime-spec, runtime.md (create, start, kill, delete, state)
- GitHub: opencontainers/runtime-spec, implementations.md (runc as reference implementation)
- Docker docs: Alternative container runtimes (containerd uses runc by default)
- GitHub: containerd CRI config docs (io.containerd.runc.v2, default runtime runc)
- CNCF blog: What’s new in CRI-O 1.31 (crun replaces runc as default; speed and memory)
- GitHub: containers/common, containers.conf(5) (runtime search order crun, runc, …)
- GitHub: cyphar/libpathrs