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 真机实测。

runcrunc运行时CLICLI 命令运维命令行2026/10/09

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-formattext日志格式,可选 text/json
--rootlessautorootless 模式,可选 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)关键字段与真实默认值如下:

字段默认值作用
ociVersion1.2.0遵循的 OCI spec 版本
root.pathrootfs根文件系统目录(相对 bundle)
root.readonlytrue根文件系统是否只读挂载
hostnamerunc实例主机名
process.terminaltrue是否分配伪终端 TTY
process.args["sh"]init(第一进程)命令
process.envPATH/TERM注入环境变量
process.cwd/工作目录
process.capabilitiesCAP_AUDIT_WRITE/CAP_KILL/CAP_NET_BIND_SERVICEbounding/effective/permitted capability 集合
process.rlimitsRLIMIT_NOFILE: 1024资源限制
process.noNewPrivilegestrue禁止获得新权限
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 后实例仍 runningSIGTERM 对 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 规避

九、参考链接