OCI 容器镜像与运行时规范
FreeGuideOnline
最新
2026-07-04
myimage/ └── blobs └── sha256 ├── # JSON 格式的 Manifest ├── # JSON 格式的 Image Config ├── # 压缩的 tar 层文件 └──
### 2.3 Image Manifest 详解
Manifest 是一个 JSON 文档,关键字段:
```json
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"digest": "sha256:...",
"size": 1234
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:...",
"size": 567890
}
]
}
config指向 JSON 格式的镜像配置。layers是一个有序列表,基础层在前,上层在后,运行时联合挂载为根文件系统。
2.4 Image Configuration 详解
Image Config 定义了如何使用镜像创建容器,部分重要字段:
{
"created": "2025-01-01T00:00:00Z",
"author": "tutorial",
"architecture": "amd64",
"os": "linux",
"config": {
"Env": ["PATH=/usr/local/sbin:/usr/local/bin:..."],
"Cmd": ["/bin/sh"],
"WorkingDir": "/",
"Volumes": {"/data": {}}
},
"rootfs": {
"type": "layers",
"diff_ids": ["sha256:abc...", "sha256:def..."]
}
}
config部分镜像 Dockerfile 中的指令(ENV、CMD、ENTRYPOINT 等)。rootfs.diff_ids是每一层未压缩内容的 SHA256,用于验证层完整性。
2.5 文件系统层与媒体类型
- 层格式:
tar归档,可选择压缩(gzip、zstd)。 - 媒体类型(Media Types):
- 清单:
application/vnd.oci.image.manifest.v1+json - 配置:
application/vnd.oci.image.config.v1+json - 层(gzip):
application/vnd.oci.image.layer.v1.tar+gzip - 层(zstd):
application/vnd.oci.image.layer.v1.tar+zstd
- 清单:
层的变更通过 Whiteout 文件实现删除,格式为以 .wh. 开头表示该文件或目录被删除。
3. OCI 运行时规范核心概念
运行时规范定义了如何将文件系统包(bundle)转换成运行的容器实例。
3.1 容器 Bundle(文件系统包)
一个 OCI Bundle 是一个目录结构:
bundle/
├── config.json # 容器的完整运行时配置
└── rootfs/ # 容器的根文件系统(可由 OCI 镜像展开得到)
3.2 config.json 关键字段
根据 OCI 运行时规范,config.json 文件必须包含:
ociVersion:规范版本(如"1.1.0")process:容器启动进程信息(terminal、user、args、env、cwd)root:文件系统路径与只读设置(path:相对 bundle 的 rootfs 路径,默认"rootfs")mounts:挂载点列表(proc、sys、cgroup 等)linux(以 Linux 为例):命名空间(namespaces)、能力(capabilities)、seccomp、资源限制等。
示例片段:
{
"ociVersion": "1.1.0",
"process": {
"terminal": true,
"user": { "uid": 0, "gid": 0 },
"args": ["/bin/sh"],
"env": ["PATH=/usr/bin"],
"cwd": "/"
},
"root": {
"path": "rootfs",
"readonly": false
},
"linux": {
"namespaces": [
{"type": "pid"},
{"type": "network"},
{"type": "mount"}
]
}
}
3.3 容器生命周期与状态
运行时规范定义了严格的状态转换:
- 创建 (creating):从 config.json 和 rootfs 初始化容器环境(命名空间、cgroup 等)。
- 已创建 (created):环境已准备,尚未执行用户进程。
- 运行 (running):用户进程已启动并执行。
- 停止 (stopped):容器主进程退出,所有关联资源保留(除非容器进程被杀死)。
允许的操作:
create→ 进入 created 状态start→ 从 created 进入 runningkill→ 发送信号,进程终止后进入 stoppeddelete→ 释放 stopped 容器的资源
3.4 运行时 hook
支持在容器生命周期关键点插入脚本(prestart、poststart、poststop),增强定制能力。
4. OCI 镜像与运行时的协作流程
一个典型的容器启动流程展示了二者如何配合:
- 解包镜像:运行时工具(如 runc)根据 OCI 镜像 Manifest 拉取 config 和所有 layers。
- 生成 rootfs:将各层按顺序提取、合并(使用 diff_ids 验证),形成
rootfs目录。 - 组合 config.json:以镜像 Config 为基础,结合用户参数(端口映射、挂载卷等)生成符合 OCI 运行时规范的
config.json。 - 启动容器:调用
create→start,容器运行。
这种解耦设计使得任何 OCI 兼容的镜像都可以被任何 OCI 兼容的运行时执行,无需转换。
5. 如何与 OCI 规范交互
5.1 使用工具构建 OCI 镜像
- Buildah:专门构建 OCI 镜像,无需守护进程。
buildah bud -t myapp . - podman:执行
podman build直接生成 OCI 标准镜像。 - docker:Docker 镜像遵循 OCI 规范(Docker 镜像格式与 OCI 略有不同,但主流运行时均兼容)。
5.2 使用符合 OCI 的运行时
- runc:OCI 参考实现,最广泛使用的低层运行时。
- crun:用 C 编写的快速替代品。
- youki:Rust 实现,内存安全。
运行示例(使用 runc 手动启动 bundle):
# 进入 bundle 目录
cd /mycontainer
runc run mycontainer
5.3 检查和转换
- skopeo:在不同仓库间复制、检查 OCI 镜像。
skopeo copy docker://alpine:latest oci:alpine-local - umoci:操作 OCI 镜像布局,可解包成 OCI bundle。
umoci unpack --image alpine:latest bundle