一文看透「容器运行时」与「容器构建」:大白话拆解 containerd、runc 与 BuildKit

前言
很多同学刚接触容器技术时,眼里只有 Docker。但随着技术的演进,尤其是 Kubernetes(K8s)统一江湖后,各种硬核名词扑面而来:containerddockerdruncrunscnerdctlBuildKit……
面试被问到一脸懵?看官方文档觉得像天书?
别慌!今天我们用**”费曼技巧”,把这些高深的概念全部放进”拍电影”和”开饭店”的生活场景里,保证你几分钟就能把现代容器生态里的容器运行时容器构建**底层逻辑彻底扒干洗净!


一、 容器运行时到底是个啥?(剧组拍戏篇)

简单来说,容器运行时就是**”让容器真正跑起来的幕后包工头”**。

早年间 Docker 大包大揽,什么活都干。后来 K8s 嫌它太臃肿,于是业界定了一个标准(CRI),把”跑容器”这个最核心的苦力活拆分了出来,这就诞生了各种独立的”容器运行时”。

把运行一个容器,想象成**”剧组拍戏”**。容器运行时分为两类,它们分工明确:

1. 高级运行时(High-level Runtime):剧组统筹(制片主任)

  • 代表人物containerd(目前最火,Docker 和 K8s 都在用)、CRI-O
  • 它的工作:负责整体调配后勤。它不管演员具体怎么演戏,只负责去网上把剧本下载下来(拉取镜像)、解压剧本、安排拍摄场地和盒饭(网络和存储管理)。

2. 低级运行时(Low-level Runtime):现场执行导演

  • 它的工作:只干最核心的一件事——盯着演员演戏。统筹把场地准备好后,它负责在现场喊”Action!”,给演员划定好活动范围(系统隔离 Namespace)和预算(资源限制 Cgroups),让代码真正跑起来。

二、 乱花渐欲迷人眼:runc / runv / runsc / rund 有何不同?

既然低级运行时是”执行导演”,那根据拍摄环境的危险程度(对安全隔离的要求),业界诞生了四位风格迥异的导演。

想象你需要安排演员(代码)在剧组(服务器)里住宿,这四个运行时代表了四种安保方案:

  • runc(标准大开间):行业默认标准(90%以上的容器都在用)。大家住在同一个大厂房里(共享宿主机内核),中间用薄木板隔开。优点是进出极快,成本极低;缺点是如果有人在房间放火(恶意攻击内核),整个厂房都会遭殃。
  • runv(独立小别墅):Kata Containers 的前身。基于虚拟机技术,直接给每个演员建一栋带独立地基的小别墅(独立微型内核)。绝对安全,但启动慢、占资源。
  • runsc(配私人管家的高级公寓):Google 开源的 gVisor。演员住公寓,但配了”私人管家”(用户态内核拦截)。演员不能直接碰大楼的电闸,必须让管家去操作。兼顾了安全和启动速度,是目前 Serverless(云函数)的最爱。
  • rund(外星人培养皿):专为 WebAssembly(Wasm)设计的运行时。里面住的不是传统 Linux 程序,而是 Wasm 模块。极致轻量,毫秒级启动,未来边缘计算的明星。

三、 对讲机与大堂经理:docker、nerdctl 与 dockerd

很多同学在服务器上习惯了敲 docker run,但你是否知道这句命令背后经历了什么?这里我们要引入”开饭店”的比喻。

1. dockerd(饭店大堂经理)

  • 角色定位:传统 Docker 架构的核心后台。它负责接待客人、设计菜单(打包镜像)、安排结账。
  • 特点:功能大而全,但体量太重。

2. containerd(后厨厨师长)

  • 角色定位:dockerd 的下属。他不关心客人是谁,只听指令去冷库拿食材(拉取镜像),然后开火炒菜(调用更底层的 runc 启动容器)。
  • 为什么 K8s 抛弃 Docker? K8s 觉得自己已经有大堂经理了,不需要 dockerd 这个中间商赚差价,于是直接绕过它,通过 CRI 接口给后厨的 containerd 下单。这就有了著名的”K8s 弃用 Docker”事件。

3. docker 与 nerdctl(你手里的对讲机)

  • docker CLI:老牌全能对讲机,专门呼叫 dockerd 大堂经理。
  • nerdctl:新式直连对讲机。为了适应没有 dockerd 的纯 containerd 环境诞生。它完美兼容 docker 命令,但直接指挥 containerd 干活,更加轻量,还支持 P2P 镜像分发等黑科技。

四、 容器构建到底靠谁?dockerd vs BuildKit

既然纯 containerd 环境下没有了 dockerd(大堂经理),那镜像(菜谱)谁来构建?记住:containerd 只负责跑容器,绝对不会进行容器构建!

为了解决这个问题,社区把”容器构建”剥离出来,做成了一个独立的神器:BuildKit(专业菜谱研发员)

传统 dockerd 构建 vs 现代 BuildKit 构建

把写 Dockerfile 打包镜像,想象成”盖一栋别墅”:

  • dockerd(老式施工队):单线程干活。必须先盖一楼,再盖二楼,最后去院子种花。哪怕种花和盖楼不冲突,工人也得干等着。而且它会把你目录下所有无关的废文件都搬到工地(全量发送 Context),速度极慢。
  • BuildKit(智能超级工厂):极度聪明。它会分析依赖树,发现”前端编译”和”后端编译”互不干扰,直接派两拨人并发干活;并且按需拿料,绝不多传废文件。配合多阶段构建,打包速度能起飞。

💡 避坑指南:
你以为你还在用落后的 dockerd 打包?其实从 Docker 23.0 开始,你敲下 docker build 时,后台默认早就在用 BuildKit 疯狂飙车了!而在纯 containerd 环境下,你只需要组合使用 nerdctl build + buildkitd 就能完美实现同样的极速容器构建。


五、 极客实操:如何切换底层运行导演?

懂了理论,我们来点硬核实操。假设你想在服务器上用更安全的 runsc(gVisor)或者跑 Wasm 的 rund,怎么把默认的 runc 换掉?

就像网约车平台呼叫”特种车辆”,只需要简单三步(以 containerd 为例):

Step 1:下载并安装”新导演”
将对应的二进制文件(如 containerd-wasm-shimrunsc)放入系统的 /usr/local/bin 目录。

Step 2:在总部登记(修改配置)
打开 containerd 的配置文件 /etc/containerd/config.toml,给新导演”上户口”:

1
2
3
# 注册 rund (Wasm运行时)
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.rund]
runtime_type = "io.containerd.rund.v1"

(修改后记得 systemctl restart containerd)

Step 3:点名上场(带参数运行)
使用对讲机发起呼叫时,带上 --runtime 参数:

1
2
# 不加参数默认用 runc,加了参数瞬间切换底座!
nerdctl run --runtime=io.containerd.rund.v1 你的Wasm镜像

(注:如果你用的是 Docker Desktop,直接在设置中勾选 “Enable Wasm”,就可以用 docker run --runtime=io.containerd.wasmedge.v1 体验了!)


六、 总结与最佳实践

把这套解耦的积木拼在一起,现代容器生态的终极轻量化与高效架构其实是这样的:

  1. 发号施令:用 nerdctl(或 docker CLI)。
  2. 容器构建:呼叫 BuildKit,享受并发编译与高效缓存的快感。
  3. 统筹调度:交给 containerd(高级运行时)专心做大管家。
  4. 底层执行:根据场景选择低级运行时,普通业务用 runc,高安全需求切 runsc,边缘计算玩 rund

技术的演进永远是朝着解耦、专业、轻量的方向发展。搞懂了容器运行时和容器构建的底层逻辑,以后无论 Kubernetes 怎么升级,还是各种新出的云原生工具,你都能一眼看透它们的本质。


📚 推荐进一步深入的参考资源

如果你想进一步修炼内功,千万不要错过以下高质量官方文档和权威资料:

  1. 容器运行时的基础心法
    • K8s 官方文档 - Container Runtimes
    • 极客时间 - 张磊老师的《深入剖析 Kubernetes》专栏(透彻讲解 Namespace 与 Cgroups 的神作)
  2. 架构演进与大局观
  3. 安全沙箱与底层隔离
    • Google gVisor 开源项目 - Architecture Guide(强烈建议看里面的隔离对比图)
  4. 轻量化容器构建与运行实战

一文看透「容器运行时」与「容器构建」:大白话拆解 containerd、runc 与 BuildKit
https://yangfanbin.cn/代码笔记/一文看透容器运行时与容器构建/
作者
Yang Fanbin
发布于
2026年3月6日
许可协议