OCI 标准与 bundle

定义

OCI(Open Container Initiative)是一组开放规范,把 Docker 早期实践中的镜像格式与运行时接口标准化。与本百科直接相关的有三份契约:

  • Image Spec:镜像清单、配置与层如何编码;
  • Distribution Spec:registry 如何用 HTTP 分发这些对象;
  • Runtime Spec:如何用一份目录描述「待启动的容器」,以及运行时应实现哪些生命周期操作。

bundle 是 Runtime Spec 中的交接物:一个目录,至少包含 config.json(进程、挂载、命名空间、资源限制等)和 rootfs/(根文件系统)。底层运行时只消费 bundle,不负责理解 Dockerfile,也不负责访问 registry。

问题背景

若镜像格式与启动接口由单一厂商定义,则构建工具、仓库、编排器与运行时无法独立演进。OCI 把「什么是镜像」和「如何启动一个容器」从产品中抽出来,使 runc、containerd、CRI-O 以及 A3S OCI Runtime 可以在同一份 bundle 语义上互换底层实现,而不要求上层改用另一套镜像格式。

机制说明

镜像规范与运行时规范的分工

构建与分发阶段处理的是镜像:可存储、可签名、可在仓库之间复制。启动阶段处理的是bundle:已经落在本机、针对这一次运行填好了挂载与进程参数的目录。

二者之间需要一次转换。产品运行时(在 A3S 中是 Box)负责:

  1. 拉取并校验镜像;
  2. 将层展开或组装为 rootfs;
  3. 把用户请求(命令、环境、卷、资源、隔离)写成 config.json
  4. 原子地发布 bundle。

底层运行时负责:校验 config.json、创建隔离、启动进程或虚拟机、记录退出状态、按身份清理。

为什么 Box 与 OCI Runtime 要拆开

ROADMAP.md 将职责写成单向依赖:Box 拥有 Docker 式用户体验与产品资源;OCI Runtime 拥有进程与隔离边界。Box 不得导入 Runtime 的驱动内部类型;Runtime 不得导入 Box 的产品类型。公共交接面是 a3s-oci-sdk 与准备好的 bundle。

这一拆分的直接后果是:在 Sandbox 路径上,Box 看起来仍像 Docker,但真正创建 namespace 的代码不在 Box 仓库里。阅读 src/runtime/src/local_execution/oci_backend.rs 时,看到的是 SDK 调用与身份围栏,而不是 clone 系统调用本身。

runc 在图中的位置

runc 是最常见的 OCI Runtime Spec 实现,也是 Docker / containerd 默认的底层执行器。A3S OCI Runtime 占据同一抽象位置:吃 bundle,产出确切的进程或 VM 状态。它额外提供代际、操作日志、native 与 utility-VM 驱动,以及给 Box 使用的类型化 SDK。它不是 Docker 守护进程,也不提供 Compose。

在 Box 中的位置

  • 工作区依赖将 a3s-oci-sdk 固定在 0.3.1,见 src/Cargo.toml
  • 创建期路由由 OciMigrationPolicy 决定。Linux 上新的 Sandbox 记录默认走 SandboxViaOci,见 ExecutionManager、Backend 与 Router
  • bundle 编译与所有者启动集中在 src/runtime/src/local_execution/oci_production.rsoci_owner.rs 以及 src/runtime/src/sandbox/

验证命令

a3s-box info

在已安装固定 a3s-oci / a3s-oci-agent 的 Linux 主机上,info 应报告 OCI 相关能力(例如符号链接支持)。随后:

a3s-box run --rm --isolation sandbox alpine:3.20 -- /bin/true

该命令的成功表示 Box 已能把镜像转换为 Runtime 可接受的 bundle,并由长期 OCI 所有者执行。

相关与易混

  • 相关:镜像与层rootfsA3S 项目族谱CRI
  • 易混:OCI 不是 Docker 的别名。Docker 是产品;OCI 是规范。bundle 也不是镜像:镜像可分发,bundle 是某一次启动的本地输入。