2. Docker Registry 原理:Registry 架构、镜像存储结构、Pull 流程详解
Docker Registry 是容器镜像的存储与分发中心,理解其内部架构、存储模型以及 Pull 流程,是优化镜像拉取速度、设计高效缓存策略的基础。本节从三个维度深入剖析 Registry 的工作原理。
2.1 Registry 架构概览
Docker Registry 采用典型的 Client-Server 架构,核心组件包括前端 API、认证授权层、存储后端以及垃圾回收模块。其设计目标是高可用、可扩展且与存储后端解耦。
| 组件 | 职责 | 说明 |
|---|---|---|
| HTTP API | 对外暴露 RESTful 接口 | 处理 GET /v2/、HEAD /v2/<name>/blobs/<digest> 等请求 |
| 认证授权 | 认证与访问控制 | 支持 Bearer 、Basic Auth,可对接 LDAP/OIDC |
| 存储驱动 | 抽象底层存储系统 | 支持 filesystem、S3、GCS、Azure Blob、OCI 等 |
| 垃圾回收 | 清理未被引用的 Blob | 通过 registry garbage-collect 命令触发 |
| 通知 Webhook | 推送事件到外部系统 | 用于 CI/CD 触发、镜像同步、安全扫描 |
架构要点: Registry 本身是无状态的,所有持久化数据均委托给存储后端。这使得 Registry 可以水平扩展,并通过 CDN 或对象存储加速全球分发。
2.2 镜像存储结构:Manifest、Blob、Config
Docker 镜像并非一个单一文件,而是由 Manifest(清单)、Config(配置) 和 Layer Blob(层数据块) 组成的逻辑集合。这种分层结构是镜像拉取加速的核心基础。
- Manifest(清单):描述镜像的元数据,包含 Config 的 Digest、所有 Layer Blob 的 Digest 列表以及媒体类型。Registry 通过 Manifest 定位整个镜像。
- Config(配置):JSON 格式的镜像配置,包含环境变量、工作目录、入口点、暴露端口以及容器历史命令。Config 本身也是一个 Blob,通过 Digest 引用。
- Layer Blob(层数据块):每一层文件系统的变更集(tar 包),通过 Content-Addressable 方式存储,以 SHA256 摘要作为唯一标识。所有层叠加后构成容器的根文件系统。
关键概念: Manifest 的媒体类型决定了镜像格式。Docker 使用
application/vnd.docker.distribution.manifest.v2+json,OCI 使用 application/vnd.oci.image.manifest.v1+json。多架构镜像则使用 Manifest List(索引)。
2.3 Pull 流程详解
当客户端执行 docker pull 时,Registry 与客户端之间发生一系列 HTTP 交互。理解每一步的请求与响应,有助于定位拉取慢的瓶颈。
- 认证握手: 客户端向
/v2/发起请求,Registry 返回 401 Unauthorized 并携带Www-Authenticate头。客户端向认证服务获取 Bearer 。 - 获取 Manifest: 客户端携带 请求
GET /v2/<name>/manifests/<tag>。Registry 返回 Manifest JSON,包含 Config 和所有 Layer 的 Digest。 - 获取 Config: 客户端通过
GET /v2/<name>/blobs/<config_digest>拉取镜像配置。该步骤通常很快,因为 Config 体积很小(几 KB)。 - 并行拉取 Layer Blob: 客户端根据 Manifest 中的 Layer Digest 列表,并发发起
GET /v2/<name>/blobs/<layer_digest>请求。Registry 返回 Layer 的 tar 数据流。 - 解压与缓存: 客户端收到 Layer 数据后,逐层解压并缓存到本地
/var/lib/docker/overlay2/(或 containerd 的 snapshotter)。
性能瓶颈分析: Pull 流程中最耗时的阶段是 步骤 4(并行拉取 Layer Blob)。瓶颈通常出现在:网络带宽、Registry 存储后端 IOPS、Layer 体积过大、或客户端并发数限制。优化方向包括:使用 P2P 分发(如 Dragonfly)、启用 Registry 缓存、或采用镜像预热。
2.4 关键参数与优化指标
| 参数 | 说明 | 优化建议 |
|---|---|---|
max-concurrent-downloads |
客户端并行拉取 Layer 的并发数 | 默认 3,可调至 6~10(需考虑带宽) |
max-download-attempts |
拉取失败重试次数 | 默认 5,网络不稳定时可适当增加 |
storage.driver |
Registry 存储后端类型 | 生产环境推荐 S3/GCS,避免本地文件系统 |
HTTP_PROXY |
Registry 出口代理 | 用于跨地域拉取时加速 |
实战要点: 在 Kubernetes 环境中,kubelet 默认使用 containerd 作为容器运行时。containerd 的 Pull 流程与 Docker 类似,但通过 CRI 接口调用。理解 Registry 原理后,可以针对性地配置
registry-mirrors 或部署 harbor 作为本地缓存 Registry,显著降低跨公网拉取延迟。