一、OCI 标准的本质
1. 容器镜像的官方定义
容器镜像是一个分层存储的归档文件(通常为 Tar 格式),包含运行容器所需的所有静态文件和元数据。其核心设计遵循开放容器倡议(OCI)标准,主要包含以下两部分
- 容器镜像不是 Docker 发明的,而是有全球统一的行业标准(OCI 标准),Docker 只是这个标准的一个实现。
- 核心对应 :Docker 镜像完全遵循 OCI 标准
2. 镜像的两大核心组成
(1)文件系统层(Rootfs)
提供容器的根文件系统(rootfs),与宿主机的文件系统隔离,是容器内进程看到的文件系统视图。
- 就是容器里能看到的所有文件(
/bin、/etc、应用代码、依赖库等),相当于容器的「操作系统文件包」。 - 和分层的对应 :Rootfs 不是一个大文件,而是由多个分层的
layer.tar组成 ,每一个layer.tar就是 Docker 镜像里的一个只读镜像层,对应 Dockerfile 的一条指令。 - 和 Overlay2 的对应 :这些
layer.tar解压后,就是 Overlay2 里的lowerdir(只读镜像层),多个layer.tar通过 Overlay2 联合挂载,合并成容器看到的统一 Rootfs 视图。
(2)配置元数据(JSON 文件)
定义容器的运行时行为,包括进程配置、安全权限、环境变量等。
- 就是镜像的「启动说明书」,告诉 Docker:用这个镜像启动容器时,要跑什么命令、用什么环境变量、给什么权限。
- 和分层的对应 :元数据是独立于分层文件系统的配置信息,不属于任何一个镜像层,是整个镜像的「全局配置」。
二、OCI 三大关键文件 ↔ Docker 分层原理
关键文件(OCI 标准)有
config.json,包含容器运行时配置;manifest.json,描述镜像的层级结构和配置文件的路径;layer.tar,每个文件系统层对应的压缩包,存储实际文件内容。
1. layer.tar:Docker 镜像分层的「实体」
- OCI 定义:每个文件系统层对应的压缩包,存储实际文件内容。
- Docker 对应 :
- 每一个
layer.tar,就是 Docker 镜像里的一个只读镜像层 ,对应 Dockerfile 的一条指令(比如RUN pip install、COPY . .)。 - 你用
docker history my-ml-app看到的每一层,本质就是一个layer.tar压缩包。 - 这些
layer.tar是只读的 ,构建完成后永远不会修改,多个镜像可以共用相同的layer.tar(比如都用python:3.12-slim基础层),这就是 Docker 分层复用的本质。
- 每一个
- 和 Overlay2 的对应 :
layer.tar解压后,就是 Overlay2 的lowerdir(只读镜像层),多个layer.tar按顺序叠加,组成完整的 Rootfs。
2. manifest.json:Docker 镜像分层的「目录索引」
- OCI 定义:描述镜像的层级结构和配置文件的路径。
- Docker 对应 :
- 相当于镜像的「目录清单」,记录了这个镜像有多少个
layer.tar、每个layer.tar的顺序、config.json的位置。 - Docker 构建镜像时,会自动生成
manifest.json,用来管理分层的顺序和依赖,保证分层按正确的顺序合并。 - 你用
docker inspect my-ml-app看到的Layers字段,就是manifest.json里记录的分层信息。
- 相当于镜像的「目录清单」,记录了这个镜像有多少个
- 核心作用 :把零散的
layer.tar,按顺序组织成一个完整的镜像,是分层结构的「管理者」。
3. config.json:Docker 镜像的「启动说明书」
- OCI 定义:包含容器运行时配置。
- Docker 对应 :
- 就是你之前问的「JSON 格式的配置文件」,里面记录了容器启动的所有配置:
CMD启动命令、ENV环境变量、WORKDIR工作目录、EXPOSE端口、用户权限等。 - 这些配置不属于任何一个镜像层,是整个镜像的全局配置,Docker 启动容器时,会读取这个文件,按配置启动容器。
- 你用
docker inspect my-ml-app看到的Config字段,就是config.json里的内容。
- 就是你之前问的「JSON 格式的配置文件」,里面记录了容器启动的所有配置:
- 核心作用:定义容器的运行时行为,是镜像从「静态分层文件」变成「动态运行容器」的关键。
三、完整链路:OCI 标准 → Docker 分层 → Overlay2 落地
1. 构建镜像时(Dockerfile → OCI 标准 → 分层存储)
- 你写 Dockerfile,每一条指令对应一个只读镜像层;
- Docker 执行
docker build,按指令生成多个layer.tar(对应 OCI 的layer.tar); - Docker 自动生成
manifest.json(记录分层顺序)和config.json(记录运行配置),符合 OCI 标准; - 所有
layer.tar、manifest.json、config.json打包成一个完整的 Docker 镜像,存储在/var/lib/docker/overlay2/目录下。
2. 启动容器时(分层 → Overlay2 → 容器运行)
- Docker 读取
manifest.json,按顺序加载所有layer.tar(只读镜像层),作为 Overlay2 的lowerdir; - Docker 创建一个空的可写层(
diff目录),作为 Overlay2 的upperdir; - Overlay2 把
lowerdir(只读分层)和upperdir(可写层)合并成merged目录(容器的 Rootfs); - Docker 读取
config.json,按配置启动容器内的进程,容器看到的就是merged目录里的统一文件系统。
3. 容器运行时(分层隔离 + 写时复制)
- 容器读文件:Overlay2 从
upperdir(可写层)往下找lowerdir(只读分层),返回最上层的文件; - 容器写文件:Overlay2 把文件从
lowerdir复制到upperdir,修改upperdir的文件,不影响lowerdir的只读分层(写时复制 CoW); - 容器删除:
upperdir(可写层)被删除,lowerdir(只读分层)完全保留,下次启动容器直接复用。
四、一张表彻底对应
| OCI 标准概念 | 对应 Docker 镜像分层原理 | 对应 Overlay2 存储 |
|---|---|---|
| 分层存储的归档文件 | Docker 镜像的分层结构,每一层对应 Dockerfile 一条指令 | Overlay2 的lowerdir(只读镜像层) |
| 文件系统层(Rootfs) | 容器的根文件系统,由多个只读分层合并而成 | Overlay2 的merged目录(容器根目录) |
| 配置元数据(JSON) | 镜像的运行时配置,config.json |
独立于分层,Docker 启动容器时读取 |
layer.tar |
每个只读镜像层的压缩包,存储实际文件 | lowerdir里的分层文件,解压后使用 |
manifest.json |
镜像分层的目录索引,记录分层顺序和配置路径 | 管理lowerdir的分层顺序,保证合并正确 |
config.json |
容器的启动说明书,记录运行时配置 | Docker 启动容器时的配置依据 |
五、总结
1. 一句话打通关系
OCI 标准定义了容器镜像的本质:分层存储的归档文件,由
layer.tar(分层文件)、manifest.json(分层索引)、config.json(运行配置)组成;Docker 镜像分层是 OCI 标准的落地实现,Overlay2 是把分层文件合并成容器 Rootfs 的底层存储驱动,三者是「标准→实现→落地」的关系。
容器镜像遵循 OCI 开放容器标准,本质是分层存储的 tar 归档文件,主要分两部分:第一部分是文件系统层(Rootfs),由多个layer.tar组成,每个layer.tar对应 Docker 镜像的一个只读层,对应 Dockerfile 的一条指令,通过 Overlay2 联合挂载成容器的根文件系统;第二部分是配置元数据,包含config.json(容器运行时配置)和manifest.json(分层结构索引),config.json定义容器启动命令、环境变量等,manifest.json管理分层顺序,保证分层按正确顺序合并。Docker 镜像分层就是 OCI 标准的落地,Overlay2 是实现分层合并的底层技术,这就是容器镜像的完整原理。
六、补充:实战验证
1. 查看镜像的 OCI 标准文件
你可以把 Docker 镜像导出,直接看到 OCI 标准的三个文件:
# 导出镜像为tar包
docker save my-ml-app -o my-ml-app.tar
# 解压tar包
tar -xvf my-ml-app.tar
# 查看解压后的文件
ls
你会看到:
- 多个
layer.tar(对应每个只读镜像层) manifest.json(分层索引)xxx.json(就是config.json,文件名是镜像 ID)
2. 查看config.json的内容
cat <镜像ID>.json
你会看到里面的Cmd、Env、WorkingDir等字段,完全对应 Dockerfile 的配置,就是图里说的「配置元数据」。
3. 查看manifest.json的内容
cat manifest.json
你会看到里面的Layers数组,记录了每个layer.tar的路径,就是图里说的「描述镜像的层级结构」。
七、常见误区纠正(彻底消除混淆)
- 误区 :
config.json是镜像分层的一部分。✅ 纠正:config.json是独立于分层的元数据,不属于任何一个layer.tar,是整个镜像的全局配置。 - 误区 :
layer.tar是可写的。✅ 纠正:layer.tar是只读的,容器的修改只会存在于 Overlay2 的upperdir(可写层),不会修改layer.tar。 - 误区 :
manifest.json是 Docker 特有的。✅ 纠正:manifest.json是 OCI 标准的一部分,所有符合 OCI 标准的容器镜像(比如 Podman、CRI-O 的镜像)都有这个文件,不是 Docker 专属。 - 误区 :Rootfs 就是一个大的 tar 包。✅ 纠正:Rootfs 是多个
layer.tar分层合并的结果,不是一个大 tar 包,分层是 OCI 标准的核心设计。