runc 常用 CLI 命令与工具详解
详解 runc 1.2.6 常用 CLI 命令与工具:spec/create/start/run/exec/kill/delete/list/state/ps/events 的参数与真实回显,并拆解 OCI bundle 的 rootfs 与 config.json 结构。所有命令与回显均为 Ubuntu 22.04 真机实测。
runc 常用 CLI 命令与工具详解
目标:详解 OCI 底层运行时 runc 的常用 CLI 命令与工具——
spec/create/start/run/exec/kill/delete/list/state/ps/events的事件参数与真实回显,并拆解其 OCI bundle(rootfs+config.json)结构。所有命令一律以 root 实测,本文已按 Ubuntu 22.04 真机实测通过。
一、概述
runc(Open Container Initiative runtime)是根据 OCI 运行时规范实现的底层容器运行时:它不负责镜像、存储与分发,只负责依据 OCI 规范真正"创建并运行"一个隔离的进程环境——创建命名空间、挂载 rootfs、设置 cgroup/凭据并拉起 init 进程。绝大多数场景下运行 docker 或 containerd 命令时,底层实际就是由它们内置的 runc 在工作。runc 没有常驻守护进程,也没有全局配置文件,它以 OCI bundle 为最小运行单元,直接以命令行方式操作。
1.1 环境信息
- 操作系统:Ubuntu 22.04.5 LTS(jammy),
x86_64,内核6.8.0-138-generic - runc 版本:
1.2.6(官方runc.amd64静态二进制,安装于/usr/local/bin/runc),spec: 1.2.0 - 最小验证 rootfs:Alpine Linux minirootfs
3.20.3(内含 busybox 的/bin/sh) - 实测入口账号:
root(演示口令q1w2e3r4) - 命令统一在 root 下执行;状态存储根目录默认
/run/runc
1.2 前置条件
runc 需要在真实 root 服务器环境运行(需内核支持命名空间与 cgroup)。使用前确认 runc 已安装且版本正确:
runc --version
which runc
runc version 1.2.6
commit: v1.2.6-0-ge89a2992
spec: 1.2.0
go: go1.23.7
libseccomp: 2.5.5
/usr/local/bin/runc
💡 演示账号使用
root/q1w2e3r4。若以普通用户执行 runc,需sudo runc run mydemo,或对 spec 做 rootless 适配(见 3.1)。
二、runc 全局命令概览(runc --help)
不带子命令执行 runc --help 会列出全部子命令与全局选项。本文实测版本 1.2.6 的完整输出如下:
runc --help
NAME:
runc - Open Container Initiative runtime
runc is a command line client for running applications packaged according to
the Open Container Initiative (OCI) format and is a compliant implementation of the
Open Container Initiative specification.
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.
To start a new instance of a container:
# runc run [ -b bundle ] <container-id>
Where "<container-id>" is your name for the instance of the container that you
are starting. The name you provide for the container instance must be unique on
your host. Providing the bundle directory using "-b" is optional. The default
value for "bundle" is the current directory.
USAGE:
runc [global options] command [command options] [arguments...]
VERSION:
1.2.6
commit: v1.2.6-0-ge89a2992
spec: 1.2.0
go: go1.23.7
libseccomp: 2.5.5
COMMANDS:
checkpoint checkpoint a running container
create create a container
delete delete any resources held by the container often used with detached container
events display container events such as OOM notifications, cpu, memory, and IO usage statistics
exec execute new process inside the container
kill kill sends the specified signal (default: SIGTERM) to the container's init process
list lists containers started by runc with the given root
pause pause suspends all processes inside the container
ps ps displays the processes running inside a container
restore restore a container from a previous checkpoint
resume resumes all processes that have been previously paused
run create and run a container
spec create a new specification file
start executes the user defined process in a created container
state output the state of a container
update update container resource constraints
features show the enabled features
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--debug enable debug logging
--log value set the log file to write runc logs to (default is '/dev/stderr')
--log-format value set the log format ('text' (default), or 'json') (default: "text")
--root value root directory for storage of container state (this should be located in tmpfs) (default: "/run/runc")
--systemd-cgroup enable systemd cgroup support, expects cgroupsPath to be of form "slice:prefix:name" for e.g. "system.slice:runc:434234"
--rootless value ignore cgroup permission errors ('true', 'false', or 'auto') (default: "auto")
--help, -h show help
--version, -v print the version
2.1 全局选项真实默认值
| 全局选项 | 真实默认值 | 说明 |
|---|---|---|
--root | /run/runc | 容器状态存储根目录,建议放在 tmpfs |
--log | /dev/stderr | 日志输出位置 |
--log-format | text | 日志格式,可选 text/json |
--rootless | auto | rootless 模式,可选 true/false/auto |
--systemd-cgroup | 关闭 | 启用 systemd cgroup,cgroupsPath 须为 slice:prefix:name 形式 |
💡 全局选项需放在子命令之前,例如
runc --root /tmp/runc-state list。
三、spec / create / start
本节演示"分步创建并启动一个实例"的完整流程:先用 runc spec 生成 bundle 配置,再 runc create 创建实例(created 态),最后 runc start 启动(running 态)。
3.1 runc spec:生成默认 config.json
在一个空目录内执行 runc spec 即生成 OCI 规范文件 config.json。--bundle/-b 可指定目录,--rootless 可生成 rootless 适配配置。
mkdir -p /opt/cli-bundle && cd /opt/cli-bundle
runc spec
ls -l config.json
-rw-r--r-- 1 root root 2598 Oct 9 10:13 config.json
runc spec --help 要点:生成的 spec 只是起始模板,默认 args 为 sh,需按 rootfs 内的实际程序调整(见 7.2);--rootless 用于生成 rootless 配置文件。
3.2 准备最小 rootfs
runc spec 只生成配置,不含根文件系统。需自行准备 rootfs/(若可直接联网则用 wget 拉取官方 minirootfs tarball 解压,亦可用已备好的 rootfs 目录):
# 以 Alpine minirootfs 为例(含 busybox /bin/sh),解压为 rootfs 目录
cd /opt/cli-bundle
wget -q https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/x86_64/alpine-minirootfs-3.20.3-x86_64.tar.gz
mkdir -p rootfs
tar -xzf alpine-minirootfs-3.20.3-x86_64.tar.gz -C rootfs
ls rootfs # 应能看到 bin lib etc usr 等目录
bin dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var
确认 rootfs 内确实有 /bin/sh(busybox):
ls -l /opt/cli-bundle/rootfs/bin/sh
cat /opt/cli-bundle/rootfs/etc/alpine-release
lrwxrwxrwx 1 root root 12 Sep 6 2024 /opt/cli-bundle/rootfs/bin/sh -> /bin/busybox
3.20.3
3.3 调整 config.json 的 init 命令
为了让实例能在后台持续运行(便于 create→start 分步演示及后续 exec/ps/events),把默认的 sh 改成一条常驻循环,并关闭 TTY。用文本编辑器或如下方式调整 process 段:
cd /opt/cli-bundle
# 关闭 TTY 分配
sed -i 's/"terminal": true/"terminal": false/' config.json
# 把 args 换成常驻循环(节选需替换的片段)
将 process.args 由 ["sh"] 改为:
"args": [
"/bin/sh",
"-c",
"while :; do echo runc-tick; sleep 1; done"
]
⚠️ 本段用
while :循环是为了制造一个"常驻 init 进程",便于演示create/start分步与exec/ps/events;它属于程序逻辑示例,不是批量部署命令。
3.4 runc create:创建 created 态实例
runc create <container-id> 按当前目录 bundle 创建实例,此时 init 进程已起但处于**挂起(created)**状态,未执行用户进程:
cd /opt/cli-bundle
runc create mydemo
runc list
ID PID STATUS BUNDLE CREATED OWNER
mydemo 3058 created /opt/cli-bundle 2026-10-09T10:14:51.985492998Z root
create 常用参数:--bundle/-b(指定 bundle 目录)、--pid-file(写 init 进程 pid)、--console-socket、--pidfd-socket、--no-pivot、--no-new-keyring。
3.5 runc start:启动用户进程
runc start <container-id> 真正执行用户定义的 init 进程,实例转为 running:
runc start mydemo &
sleep 2
runc list
runc-tick
runc-tick
ID PID STATUS BUNDLE CREATED OWNER
mydemo 3058 running /opt/cli-bundle 2026-10-09T10:14:51.985492998Z root
💡 上面多行的
runc-tick是 rootfs 内 init 循环打印到标准输出的内容(terminal: false时输出直接继承)。runc start无其他参数,create与start之间可插入state/list等查看命令(见五)。
四、exec / run / kill / delete
本节覆盖实例运行期的进出与控制操作:run(一步到位)、exec(进入运行实例)、kill(发信号)、delete(回收资源)。
4.1 runc run:create + start 一步到位
runc run <id> 等价于 create + start。--detach/-d 让实例在后台运行且 init 进程成为守护进程的最新子进程(re-parented),常与 --pid-file 配合记录 init pid:
cd /opt/cli-bundle
runc run --detach --pid-file det-pid.txt demodetach
echo "pid=$(cat det-pid.txt)"
runc list
pid=3266
ID PID STATUS BUNDLE CREATED OWNER
demodetach 3266 running /opt/cli-bundle 2026-10-09T10:15:31.215352613Z root
run 除继承 create 的参数外,额外支持:--detach/-d、--keep(退出后保留实例,不自动删除)、--no-subreaper。非 detach 且 init 退出后,默认会自动删除实例。
4.2 runc exec:在运行实例内执行进程
runc exec <id> <command> 在运行中的实例内新起一个进程(复用其命名空间):
runc exec mydemo /bin/sh -c "id; hostname; ps"
uid=0(root) gid=0(root)
runc
PID USER TIME COMMAND
1 root 0:00 /bin/sh -c while :; do echo runc-tick; sleep 1; done
18 root 0:00 sleep 1
19 root 0:00 ps
exec 常用参数:-e/--env(注入环境变量)、-u/--user(运行 UID[:GID])、--cwd(工作目录)、-t/--tty(分配 TTY)、-d/--detach、-p/--process(从 process.json 加载进程描述)、--cgroup(在指定子 cgroup 内运行)。示例注入环境变量:
runc exec -e RELEASE=prod mydemo /bin/sh -c "echo release=\$RELEASE"
release=prod
4.3 runc kill:向 init 进程发信号
runc kill <id> [signal] 向实例 init 进程发送信号,默认 SIGTERM:
runc kill mydemo SIGTERM
sleep 1
runc list
ID PID STATUS BUNDLE CREATED OWNER
mydemo 3058 running /opt/cli-bundle 2026-10-09T10:14:51.985492998Z root
⚠️ 注意:向 busybox
sh这类 init 进程发送SIGTERM,并不保证实例一定退出——sh收到 SIGTERM 后可能不立即终止(实测本例仍是running)。确认停止实例请改用明确信号:
runc kill mydemo SIGKILL
sleep 1
runc list
ID PID STATUS BUNDLE CREATED OWNER
mydemo 3058 stopped /opt/cli-bundle 2026-10-09T10:14:51.985492998Z root
💡
state查看stopped态:pid已变为0、status为stopped(见 5.2)。
4.4 runc delete:回收资源
runc delete <id> 删除实例占用的资源并从列表移除(适用于已 stopped 的实例)。实测:对仍 running 的实例直接 delete 会报错:
runc delete mydemo
time="2026-10-09T10:15:10Z" level=error msg="cannot delete container mydemo that is not stopped: running"
先 kill 使实例变为 stopped,再 delete 即成功:
runc kill mydemo SIGKILL
runc delete mydemo
runc list
ID PID STATUS BUNDLE CREATED OWNER
delete 支持 --force/-f,对仍运行中的实例用 SIGKILL 强制删除。
五、list / state
5.1 runc list:列出全部实例
runc list 默认以 table 输出。-q/--quiet 只显示 ID,-f/--format 可取 table 或 json:
runc list
ID PID STATUS BUNDLE CREATED OWNER
mydemo 3058 running /opt/cli-bundle 2026-10-09T10:14:51.985492998Z root
runc list -q
mydemo
runc list -f json
[{"ociVersion":"1.2.0","id":"mydemo","pid":3058,"status":"running","bundle":"/opt/cli-bundle","rootfs":"/opt/cli-bundle/rootfs","created":"2026-10-09T10:14:51.985492998Z","owner":"root"}]
💡
list列表基于--root(默认/run/runc)下的状态存储;用非默认--root创建的实例需用相同--root查看。
5.2 runc state:查看单个实例状态
runc state <id> 输出某实例的 JSON 状态信息。三种状态的实测差异:
runc state mydemo
created 态:
{
"ociVersion": "1.2.0",
"id": "mydemo",
"pid": 3058,
"status": "created",
"bundle": "/opt/cli-bundle",
"rootfs": "/opt/cli-bundle/rootfs",
"created": "2026-10-09T10:14:51.985492998Z",
"owner": ""
}
running 态:status 变为 running、owner 为 root;stopped 态:pid 变为 0、status 为 stopped。
六、ps / events
6.1 runc ps:查看实例内进程
runc ps <id> 输出实例内进程(类似宿主机 ps)。-f/--format 可取 table/json:
runc ps mydemo
UID PID PPID C STIME TTY TIME CMD
root 3058 1 0 10:14 ? 00:00:00 /bin/sh -c while :; do echo runc-tick; sleep 1; done
root 3105 3058 0 10:15 ? 00:00:00 sleep 1
6.2 runc events:统计事件
runc events 用于持续输出实例的 OOM 通知与 cpu/memory/io 统计(默认每 5s 一份流式 JSON)。--stats 改为取一次统计后立即退出;--interval 可改采集间隔:
runc events --stats mydemo
{"type":"stats","id":"mydemo","data":{"cpu":{"usage":{"total":41872000,"kernel":32681000,"user":9191000},"throttling":{},"psi":{"some":{"avg10":0,"avg60":0,"avg300":0,"total":1281},"full":{"avg10":0,"avg60":0,"avg300":0,"total":979}}},"cpuset":{"cpu_exclusive":0,"mem_hardwall":0,"mem_exclusive":0,"memory_migrate":0,"memory_pressure":0,"mem_spread_page":0,"sched_load_balance":0},"memory":{"usage":{"limit":0,"failcnt":0},"kernel":{"limit":0,"failcnt":0}},"pids":{"current":2},"blkio":{"psi":{"some":{"avg10":0,"total":0},"full":{"avg10":0,"total":0}}},"hugetlb":{},"network_interfaces":null}
上面的 cpu.usage.total/kernel/user 为纳秒计 CPU 用量,pids.current 为当前实例内进程数(本例为 2);cpuset/memory/blkio 等段按规范输出对应控制器的统计与 PSI 数据。
⚠️ 流式
runc events <id>(监听 OOM 事件)依赖对 cgroup 目录加 inotify watch。在受限的低权限环境下实测会提示unable to add inotify watch: no such file or directory;以真实 root 服务器运行为准即可正常输出。
七、bundle 结构
OCI bundle 是一个目录,内含 config.json(规范文件)与 rootfs/(根文件系统),是 runc 运行的最小单元。本文实测 bundle 位于 /opt/cli-bundle。
7.1 rootfs
rootfs/ 是实例的根文件系统。runc 以 process.args 作为 init 在此 rootfs 内执行,默认挂载点为 /proc、/dev、/sys 等。本文 rootfs 为 Alpine minirootfs 3.20.3(内含 busybox /bin/sh)。
7.2 config.json 关键字段
runc spec 生成的默认 config.json(version 1.2.0)关键字段与真实默认值如下:
| 字段 | 默认值 | 作用 |
|---|---|---|
ociVersion | 1.2.0 | 遵循的 OCI spec 版本 |
root.path | rootfs | 根文件系统目录(相对 bundle) |
root.readonly | true | 根文件系统是否只读挂载 |
hostname | runc | 实例主机名 |
process.terminal | true | 是否分配伪终端 TTY |
process.args | ["sh"] | init(第一进程)命令 |
process.env | PATH/TERM | 注入环境变量 |
process.cwd | / | 工作目录 |
process.capabilities | CAP_AUDIT_WRITE/CAP_KILL/CAP_NET_BIND_SERVICE | bounding/effective/permitted capability 集合 |
process.rlimits | RLIMIT_NOFILE: 1024 | 资源限制 |
process.noNewPrivileges | true | 禁止获得新权限 |
mounts | /proc /dev /dev/pts /dev/shm /dev/mqueue /sys /sys/fs/cgroup | 预置标准挂载点 |
实测默认 process/root/mounts 片段:
"process": {
"terminal": false,
"user": { "uid": 0, "gid": 0 },
"args": ["/bin/sh", "-c", "while :; do echo runc-tick; sleep 1; done"],
"env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm"
],
"cwd": "/"
},
"root": { "path": "rootfs", "readonly": true },
"hostname": "runc"
7.3 命名空间与 cgroup
config.json 的 linux.namespaces 默认创建 pid、network、ipc、uts、mount、cgroup 六类命名空间(type 列表实测):
"linux": {
"namespaces": [
{ "type": "pid" },
{ "type": "network" },
{ "type": "ipc" },
{ "type": "uts" },
{ "type": "mount" },
{ "type": "cgroup" }
],
"resources": {
"devices": [ { "allow": false, "access": "rwm" } ]
}
}
- 默认
resources.devices为allow: false,即默认拒绝实例内对设备的访问; - cgroup 路径由
linux.cgroupsPath控制;若未指定,runc 按 vfs/经典 cgroup 自动挂载。使用 systemd 托管的系统可在全局选项加--systemd-cgroup(cgroupsPath须为slice:prefix:name,如system.slice:runc:434234);runc update可在运行期动态调整 cpu/memory 等资源约束。
八、常见问题
| 问题 | 处理 |
|---|---|
runc run 报 operation not permitted | 需以 root 执行(sudo runc run mydemo)或用 --rootless 做 rootless 适配;受限低特权环境不支持创建命名空间 |
对已退出实例执行 runc state 提示 container does not exist | 非 detach 模式 init 退出后 runc 自动删除实例(list 为空属正常);需保留用 --keep 或 create/start 分步 |
runc kill <id> SIGTERM 后实例仍 running | SIGTERM 对 busybox sh 等 init 不保证退出;改用 SIGKILL 确认停止 |
对 running 实例 runc delete 报 cannot delete container mydemo that is not stopped: running | 需先 kill 令其 stopped,或加 --force/-f 强制(SIGKILL)删除 |
启动报 sh: not found | 默认 args: ["sh"],需按 rootfs 内 ls rootfs/bin 实际存在的程序修改 process.args |
runc events 报 unable to add inotify watch | 监听 OOM 事件依赖对 cgroup 的 inotify watch,受限环境受限;真实 root 服务器正常。一次统计用 runc events --stats 规避 |
九、参考链接
- runc 官方仓库:https://github.com/opencontainers/runc
- runc 官方 Releases(含离线二进制与 sha256sum):https://github.com/opencontainers/runc/releases
- OCI 运行时规范 runtime-spec:https://github.com/opencontainers/runtime-spec
- OCI features 规范(
runc features输出类型定义):https://github.com/opencontainers/runtime-spec/blob/main/features.md - Alpine minirootfs 下载:https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/x86_64/