镜像存储结构
在Docker Registry v2 中,镜像是以分层的形式存储的,采用了内容寻址和分层存储的机制。
各个结构的示意图如下:
假设存储一个名为 my-app:latest
的镜像,目录结构如下:
registry/
└── docker
└── registry
└── v2
├── blobs/
│ └── sha256/
│ ├── <digest-of-layer-1>/
│ ├── <digest-of-layer-2>/
│ ├── <digest-of-layer-3>/
│ └── <digest-of-config>/
└── repositories/
└── my-app/
└── _manifests/
└── tags/
└── latest/
└── current/
└── link
下面分别介绍各个部分的结构.
image name
镜像名:镜像名是用户访问镜像的基础标识,通常以<仓库名>:<标签>的形式表示,例如:my-registry.com/my-app:latest.
tag
标签:镜像标签是对具体镜像版本的友好引用。标签本身并不包含实际数据,而是指向一个Manifest,多个标签可以指向同一个 manifest,实现镜像的版本管理和复用。
tags/latest/current/link 指向对应的 Manifest。
manifest
manifest是一个JSON 格式的文本文件,存储在 Docker Registry 中,用于描述一个镜像的组成部分,主要包括以下三部分:
镜像的各层(Layers)的 Digest。
镜像的配置(Config),包括启动命令、环境变量等。
层的媒体类型(Media Type)和大小。
manifest是一个JSON 格式的文本文件,存储在 Docker Registry 中,用于描述一个镜像的组成部分。存储在manifests文件夹下。
manifest结构举例如下:
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 7023,
"digest": "sha256:c54a2cc56cbb2f0406b44acb6b5f5b3dbb21f19d50f8eedc5bba7d6a9dd67f58"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 32654,
"digest": "sha256:ec4a7858f0b2561c830233f6e1f3b6a08efc1d7d706032d22b9a6f0d69a7c4cc"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 16724,
"digest": "sha256:4cf1eda4d058d6915a4ea26453ed309b6937383c6e5b51a6da64e24835a5c303"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 73109,
"digest": "sha256:8c662931926fae5a8fd0d7a3096f7b44c29b28a8e6a4b5e2a48b00601234abcd"
}
]
}
layer
镜像是由多个层组成的,层是文件系统的增量变化记录,每一层存储新增修改或删除的文件.层之间是有序的,构成了镜像的完整文件系统。每一层在 Docker Registry 或本地存储中被保存为一个压缩的 tar 文件,包含该层的文件和目录结构。
添加文件。
修改文件。
删除文件。
镜像的每一层以内容哈希值(Digest, SHA256)为文件名存储在 blobs目录中。每一层的 Blob 存储在 blobs/sha256下。
分层的具体内容
每一层表示镜像构建过程中对文件系统的增量修改。这些修改通常包括新增文件、修改文件、删除文件、安装软件等操作。每一层只记录从上一层的增量变化,因此镜像存储高效且支持分层复用。
以下面这个构建镜像的 Dockerfile 举例
# 基础镜像
FROM ubuntu:20.04
# 设置工作目录
WORKDIR /app
# 安装软件
RUN apt-get update && apt-get install -y python3
# 复制本地文件到镜像
COPY app.py /app/app.py
# 设置默认启动命令
CMD ["python3", "app.py"]
当这个 Dockerfile 被执行时,每条指令(Instruction)都会生成一层layer.
FROM ubuntu:20.04
这一层使用了基础镜像 ubuntu:20.04,其内容包含该镜像的文件系统快照。
例如:
/bin/bash
/etc/apt/
/lib/
...
这是整个镜像的第一个层,所有后续层都基于它。
WORKDIR /app
这一层的内容是工作目录的变更。 实际上,这个层并不会在文件系统中创建新文件或目录,而是仅在元数据中记录 "工作目录为 /app" 的设置。
RUN apt-get update && apt-get install -y python3
这一层包含执行命令后对文件系统的修改: 更新 apt-get 缓存(通常修改 /var/lib/apt/lists/)。 安装 Python3(添加文件到 /usr/bin/python3 和相关依赖到 /usr/lib/ 等)。 例如,新增的文件可能包括:
/usr/bin/python3
/usr/lib/python3/
/var/lib/dpkg/
/etc/apt/sources.list
...
COPY app.py /app/app.py
这一层的内容是将 app.py 文件从构建上下文复制到镜像内的 /app/ 目录。
CMD ["python3", "app.py"]
这一层不改变文件系统,只更新镜像的元数据,记录默认的启动命令。 镜像中的 CMD 命令只是设置运行容器时的默认行为。
整个过程可以用一张图表表示:
blob
Blob是存储镜像层和配置的基本单元,每个 Blob 对应镜像的一个层或配置文件。
Blob 存储是无状态的,可以独立存放在不同的后端存储中(如本地文件系统、Amazon S3、Google Cloud Storage 等)。通过配置文件 config.yml 可以切换存储后端。