OCI 镜像规范详解
在容器技术发展的早期,Docker 镜像是事实上的标准。随着容器生态的爆发,为了确保不同容器运行时(如 Docker, containerd, CRI-O, Podman 等)和构建工具之间的互操作性,Open Container Initiative (OCI) 成立并推出了 OCI Image Specification。
本文将基于最新的 OCI Image Specification 详细解读 OCI 镜像的构成及其背后的技术细节。
OCI 镜像规范概览
OCI 镜像规范定义了 OCI 镜像的结构。简单来说,一个 OCI 镜像包含以下几个核心部分:
- Image Manifest (镜像清单): 描述构成镜像的组件(包括配置和层)。
- Image Index (镜像索引): (可选) 指向多个 Manifest 的列表,通常用于支持多架构(如
amd64,arm64)。 - Image Layout (镜像布局): 镜像在文件系统上的目录结构。
- Filesystem Layer (文件系统层): 包含了容器文件系统的更改集 (Changeset)。
- Image Configuration (镜像配置): 包含了镜像的元数据(如启动命令、环境变量)以及层级顺序。
这些组件共同工作,使得镜像可以被构建、传输、校验并最终运行。
核心概念:Content Descriptors (内容描述符)
在深入各个组件之前,必须先理解 Content Descriptor。它是 OCI 规范中用来引用内容的通用方式。
一个描述符(Descriptor)就是一个 JSON 对象,它告诉我们“去哪里找内容”、“内容长什么样”以及“内容的指纹是什么”。核心字段包括:
mediaType: 内容的类型(例如:application/vnd.oci.image.manifest.v1+json)。digest: 内容的哈希摘要(通常是 sha256),用于唯一标识和校验内容。size: 内容的大小(字节)。
1 | { |
OCI 广泛使用了 Merkle Directed Acyclic Graph (DAG) 结构,描述符就是图中的边,连接了不同的组件。
组件结构详解
OCI 镜像的结构关系如下图所示:

1. Image Manifest (镜像清单)
Manifest 是镜像的“物料清单”。对于一个特定的架构和操作系统,Manifest 定义了镜像由哪些层组成,以及配置文件的位置。
一个典型的 Manifest JSON 结构如下:
1 | { |
config: 引用镜像配置 Blob。layers: 一个有序数组,引用了组成文件系统的各个层 Blob。数组索引 0 是底层 (Base Layer),后续层依次叠加。
2. Image Configuration (镜像配置)
Configuration 是一个 JSON 文档,包含了将镜像转换为运行时 Bundle 所需的信息。它不包含文件系统的实际内容,而是包含元数据。
主要包含:
architecture/os: 适用的 CPU 架构和操作系统。config: 运行时配置,如Env(环境变量),Cmd(默认命令),Entrypoint,User,WorkingDir等。rootfs: 引用了由于层叠加而产生的 Diff IDs,用于校验文件系统完整性。history: 描述了每一层是如何构建出来的(例如Dockerfile中的指令)。
3. Filesystem Layers (文件系统层)
Layers 包含了文件系统的实际变化。每一个层通常是一个 .tar 或 .tar.gz 归档文件。
OCI 镜像采用分层存储和写时复制 (CoW) 策略。每一层只记录相对于上一层的 变化 (Changeset) 。变化主要有三种类型:
- Add (新增): 包含了完整的文件或目录内容。
- Modify (修改): 包含了修改后文件的完整内容。在 Tar 包中,增加和修改的表现形式是一样的(即存在该文件)。
- Delete (删除): OCI 使用 Whiteouts (遮盖文件) 来表示删除。
关于 Whiteouts (遮盖文件)
如果我们在上层删除了下层的一个文件 /etc/my-app-config,我们不能直接从 Tar 包里把这个文件拿掉(因为下层是只读的)。相反,我们在新层中创建一个特殊的文件,名字叫 .wh.my-app-config。
运行时在联合挂载(Union Mount)时,看到 .wh. 前缀的文件,就会知道要“遮挡”住下层的同名文件,从而实现删除效果。
还有一个特殊的 Opaque Whiteout (.wh..wh..opq),用于隐藏父目录下的所有子项。
1 | # 示例:层内容 |
4. Image Index (镜像索引)
Image Index 是一个更高层级的 Manifest。它本身不包含层或配置,而是包含了一个指向其他 Manifest 的列表。
这主要用于多平台支持。当你 docker pull my-image:latest 时,客户端会先获取 Index,然后根据当前的机器架构(如 linux/amd64),找到列表中对应的 Manifest 并下载。
1 | { |
OCI 生态工具推荐
了解 OCI 规范后,值得深入了解两个在云原生生态中被广泛使用的工具和库,它们完美体现了 OCI 标准带来的互操作性。
Skopeo
Skopeo 是一个功能强大的命令行工具,用于对容器镜像和镜像库执行各种操作。与其他工具不同,Skopeo 的最大优势在于它无需运行容器守护进程(如 Docker Daemon) 即可工作。
常用场景示例:
远程检视 (
skopeo inspect)
在不下载(Pull)镜像层的情况下,直接读取远程仓库中镜像的 Manifest 和配置信息。这在 CI/CD 流水线中非常实用,可以快速检查镜像标签、架构或创建时间。命令:
1
skopeo inspect docker://hub.example.io/library/alpine:latest
输出示例 (JSON):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29skopeo inspect docker://hub.example.io/library/alpine:latest --tls-verify=false
{
"Name": "hub.example.io/library/alpine",
"Digest": "sha256:9d04ae17046f42ec0cd37d0429fff0edd799d7159242938cc5a964dcd38c1b64",
"RepoTags": [
"3.10",
"3.22",
"latest"
],
"Created": "2025-10-08T11:04:56Z",
"DockerVersion": "",
"Labels": null,
"Architecture": "amd64",
"Os": "linux",
"Layers": [
"sha256:2d35ebdb57d9971fea0cac1582aa78935adf8058b2cc32db163c98822e5dfa1b"
],
"LayersData": [
{
"MIMEType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"Digest": "sha256:2d35ebdb57d9971fea0cac1582aa78935adf8058b2cc32db163c98822e5dfa1b",
"Size": 3802452,
"Annotations": null
}
],
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
]
}镜像复制与格式转换 (
skopeo copy)
支持在不同的存储机制之间直接复制镜像。例如,将 Docker Hub 上的镜像直接下载并转换为符合 OCI Layout 标准的本地文件目录,而无需中间环节。命令:
1
2# 将 Docker 在线镜像复制为本地 OCI 目录结构
skopeo copy docker://docker.io/library/alpine:latest oci:/tmp/alpine-layout:latest输出:
1
2
3
4
5Getting image source signatures
Copying blob 05455a5d5d3e done
Copying config 124c7d2707 done
Writing manifest to image destination
Storing signatures
containers/image 库
containers/image(也被称为 image library)是上述 Skopeo 以及 Podman、Buildah 等下一代容器工具背后的核心库。
这是一个 Go 语言库,提供了一套通用的 API 来处理容器镜像的传输、签名、及其元数据管理。它抽象了底层的存储细节,支持多种 传输协议 (Transports) :
docker://:访问标准的远程 Docker/OCI 注册表。docker-daemon://:直接操作 Docker 守护进程的本地存储。oci://:操作符合 OCI 目录布局(OCI Layout)的本地镜像。dir://、tarball://等:支持本地目录和归档文件。
正是因为有了 containers/image 库的底层支持,OCI 生态中的工具才能实现跨平台、跨存储后端的无缝互操作,真正践行了 OCI “一次构建,到处运行” 的理念。
代码示例 (Go) :
以下代码展示了如何使用该库编程将一个远程 Docker 镜像复制到本地 OCI 目录中。
1 | package main |
执行结果:
1 | Getting image source signatures |
总结
OCI 镜像规范不仅仅是一个文件格式标准,它构成了现代云原生基础设施的基石。通过解耦 Manifest (清单)、Config (配置) 和 Layers (数据) ,它实现了高度的灵活性和互操作性。
本文的核心要点回顾:
- 内容寻址 (Content Addressable): 一切皆通过 Digest 引用,确保内容不可篡改且易于去重。
- 分层机制: 极大地优化了存储和传输效率,公共的基础镜像层只需存储一份。
- 多架构支持: Image Index 使得同一个标签可以无缝支持多种硬件平台。
- 生态互通: 借助 Skopeo 和
containers/image等工具,我们可以轻松在不同环境(Docker, OCI Layout, Remote Registry)之间迁移和操作镜像。
理解这些底层细节,有助于我们更好地进行容器镜像的构建优化、安全扫描以及故障排查,从而构建更高效、更安全的云原生应用。





