opencontainers/runc: the OCI runtime underneath Docker and containerd
CLI tool for spawning and running containers according to the OCI specification
At a glance
- What is it?
- runc is the low-level Linux CLI that turns an OCI bundle into a running container. It is a building block for orchestrators, not a tool most developers should drive by hand, and building it pulls in libseccomp and optionally libpathrs.
- Who is it for?
- Adopt runc if you are building or debugging a container platform, or you need to see exactly what an OCI bundle turns into at the kernel level. Do not adopt it as a developer-facing container tool: it has no image pulling, no networking setup and no daemon, so containerd or Docker belongs in front of it.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What opencontainers/runc actually does
The README opens with a one-line definition: runc is a CLI tool for spawning and running containers on Linux according to the OCI specification. That sentence is the whole product. runc takes a filesystem bundle containing an OCI runtime spec (config.json) and a root filesystem, and it creates the namespaces, cgroups, mounts and security settings described there, then execs the configured process. It is the last step in the chain that starts a container, not the first.
The audience follows from that. If you run docker run or kubectl apply, runc is somewhere underneath you, invoked by a higher-level daemon, and you will never type its name. The people who install runc directly are platform engineers building a container runtime layer, SREs debugging why a container will not start, and anyone doing security work on namespace and cgroup isolation. The README also points at a third-party security audit performed by Cure53, with the report linked from the repository, which tells you the project expects adversarial review of exactly those isolation boundaries.
How runc builds a container from an OCI bundle
The repository layout mirrors the container lifecycle rather than a single monolith. Top-level Go files are named after the operations they implement: create.go, start.go, exec.go, kill.go, pause.go, restore.go, delete.go, list.go, state.go. The heavy lifting lives in libcontainer/, which is the library that talks to the kernel. The CLI is a thin layer over it, wired with github.com/urfave/cli/v3.
Data flow is deliberately simple. runc create reads config.json, sets up the container's namespaces and cgroup, and leaves the process paused. runc start then signals it to exec the configured entrypoint. runc state reports what exists; runc delete tears it down. Checkpoint and restore are separate code paths (checkpoint.go, restore.go) that depend on CRIU, and the build tag runc_nocriu disables them entirely, which is the honest way to say the feature is optional.
Two dependencies shape the security posture. github.com/seccomp/libseccomp-golang provides syscall filtering, and cyphar.com/go-pathrs plus github.com/cyphar/filepath-securejoin handle path resolution, which is where container escapes historically come from. The build tag table in the README lists seccomp and libpathrs as enabled by default, with libseccomp and libpathrs as their respective dependencies. That means a default build is not a pure-Go static binary; it links C and, for libpathrs support, a Rust library.
Runc install on Ubuntu and the first container you run
runc only supports Linux, and the README says the minimum Go version is in the header of go.mod. On Ubuntu or Debian, the dependency line is explicit:
apt update && apt install -y make gcc linux-libc-dev libseccomp-dev pkg-config gitThen clone into a GOPATH-style tree and build. The Makefile installs the binary to $(PREFIX)/sbin, which defaults to /usr/local/sbin, so the result is /usr/local/sbin/runc.
cd github.com/opencontainers
git clone https://github.com/opencontainers/runc
cd runc
make
sudo make installYou can confirm the binary and its embedded commit with runc --version. Build tags are controlled through RUNC_BUILDTAGS, where a leading minus removes a default tag. This example drops seccomp and adds the CRIU-disabling tag, which is what you would do on a host without libseccomp headers:
make RUNC_BUILDTAGS="runc_nocriu -seccomp"For a first real use you need a bundle, which runc does not create for you. The README does not walk through bundle layout, so treat docs/ and man/ as the real reference. If you want libpathrs path safety, note the README requires at least libpathrs 0.2.5, that few distributions package it, and that the repository's own script/build-libpathrs.sh is described as completely unsupported.
Where runc is the wrong tool
The clearest limitation is scope. runc does not pull images, does not set up container networking, does not manage volumes, and does not run as a daemon. Every one of those is a layer above it. If you hand runc a bundle whose rootfs you assembled yourself, that is your responsibility, including the parts that are easy to get wrong.
Platform support is the second hard boundary. The README states runc only supports Linux. There is no macOS or Windows runtime here, so any workflow that assumes a cross-platform CLI is out of scope.
Build complexity is the third. A default build wants libseccomp and libpathrs, and the README is candid that libpathrs packages are rare enough that local builds are usually necessary, with Rust 1.63+ and tools like clang and lld required. You can remove the tag, but then you are running a different security configuration than the project's default, and the README does not document what you give up in that case. That silence is worth weighing: the build tag table says what the tag does, not what its absence costs.
Finally, version drift matters because runc sits under other software. A runtime upgrade can change container behaviour for everything above it, and the CHANGELOG.md is the only place that records those changes.
Runc vs containerd, and what crun changes
The comparison people search for most is runc versus containerd, and the difference is architectural rather than competitive. containerd is a daemon that manages images, snapshots, and container lifecycle over a gRPC API, and it calls an OCI runtime, commonly runc, to actually start the process. runc is the runtime; containerd is the manager. Docker sits above containerd in the same way. Choosing between them is not a choice at all if you want image pulls and a persistent API, because runc provides neither.
The more interesting alternative is crun, a separate OCI runtime implementation. The README gives no comparison, so the honest statement is that both implement the same OCI runtime interface and differ in implementation language and dependency footprint. runc links libseccomp and, by default, libpathrs; a runtime written in C has a different set of build and linkage trade-offs. Whether that matters depends on your distribution's packaging constraints, not on a feature list.
For checkpoint and restore, the alternative is not another runtime but the CRIU dependency itself. runc delegates to github.com/checkpoint-restore/go-criu/v8, and the runc_nocriu tag removes that path. If you need live migration, you are depending on CRIU working on your kernel, not on runc alone.
Licence, releases and upgrade cost
runc is Apache-2.0, with a NOTICE file in the repository root. Apache-2.0 includes an explicit patent grant and requires attribution and notice retention when you redistribute. That is a permissive arrangement, but if you vendor runc into a product, the NOTICE file travels with it. This is a description of the licence text, not legal advice; your own counsel decides what your distribution obligations are.
Releases are signed, and the README points to the runc.keyring file in the repository root as the list of signing keys. The most recent entries are v1.5.1 from 2026-07-14 and v1.5.0 from 2026-06-19, following a v1.5.0-rc.3 candidate on 2026-06-13. The release titles are jokes rather than changelogs, so the substance lives in CHANGELOG.md and RELEASES.md.
Upgrade cost is dominated by the build, not the binary. Because default tags pull in libseccomp and libpathrs, a rebuild after a version bump can require matching library versions, and the README pins a floor of libpathrs 0.2.5. The Makefile supports EXTRA_VERSION for stamping custom builds, which is useful when you need to identify which build is running on a host. Note also that EXTRA_BUILDTAGS is deprecated in favour of RUNC_BUILDTAGS, with a comment saying it will be removed for runc 1.6, so any build scripts still using the old variable will start warning.
Editorial conclusion
Adopt runc if you are building or debugging a container platform, or you need to see exactly what an OCI bundle turns into at the kernel level. Do not adopt it as a developer-facing container tool: it has no image pulling, no networking setup and no daemon, so containerd or Docker belongs in front of it. Before you install, check the Go version in go.mod, confirm libseccomp and pkg-config are present, and decide whether the default libpathrs build tag is something your distribution can support.
Frequently asked questions
What is runc in Docker?
runc is the OCI runtime that actually spawns and runs the container process on Linux. Docker manages images and networking and then hands the container to a runtime such as runc to create namespaces, cgroups and mounts from the bundle.
Is crun better than runc?
The runc README does not compare the two. Both are OCI runtime implementations, so the practical difference is in implementation language and dependency footprint: runc links libseccomp and, by default, libpathrs, which affects how it builds and packages on a given distribution.
Why are people moving away from Docker?
This is outside what the runc repository documents. runc is a component that sits below Docker and containerd rather than a replacement for either, so the project's own material says nothing about Docker adoption trends.
Is Apple's container runtime better than Docker?
The runc repository says nothing about Apple's container runtime. runc itself only supports Linux, so a comparison involving Apple's runtime is not covered by this project's documentation.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/opencontainers-runc)