Atlantis
GitHub Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

3.4 推送容器镜像

1. 推送镜像流程

  1. 解析镜像名称和标签:解析提供的镜像名称和标签,例如 registry-name/username/image:v1,未指定 registry-name 时,默认使用 docker.io。
  2. 推送镜像分层(Blob):
    1. Docker 会将镜像分解成多个层级,并逐层推送到镜像仓库
    2. 对于每一个镜像层:
      1. 首先检查镜像层是否存在:HEAD /v2/<image>/blobs/<layer-digest>
      2. 若镜像存在层存在则跳过,若不存在则先执行:POST /v2/<image>/blobs/uploads/ 获取上传 URL,然后执行 PATCH /v2/<image>/blobs/uploads/<upload-id> 分片上传,或者使用 PUT /v2/<image>/blobs/uploads/<upload-id>?digest=<layer-digest> 整体上传
  3. 推送清单(Manifest): 当所有分层都上传完毕后,Docker 会将镜像的清单文件 (Manifest) 推送到镜像仓库:PUT /v2/<image>/manifests/<tag>

访问 /v2/<images> 开头的接口都会一并发送调用 /v2/token 获取到的 Token 用于鉴权(如果本地有账号密码的话),如果遇到 Token 失效或者没有权限操作对应的镜像时,就会报错。

总得来说,先推送依赖项(blobs),再推送索引(manifest),在多架构镜像中也有类似情况,需要先推送单架构镜像的 manifest,再推送多架构镜像的 manifest.list。

2. 镜像大小限制

我曾经在推送镜像时遇到过 HTTP 状态码 413 错误,提示 Request Entity Too Large,排查后发现客户的单层镜像高达 9.6GB,超过了公共镜像仓库的单层 2000MB 限制。

对于单架构镜像来说,每个镜像都是由多个镜像层组成的,docker 以及 registry 暂无镜像大小限制,而 Harbor 镜像大小的限制则有两处,一个是单层镜像大小不能超过 10GB,另一个则是可选配置的项目存储空间大小。 dockerhub 暂无镜像大小限制的明确说明,从网上的资料看也是限制单层 10GB,总计不超过 100GB。

过大的镜像层对推送镜像的操作来说并不友好,特别是请求经过反向代理的情况,如果使用 PUT 请求完整传输单层镜像,会需要占用大量的缓存空间。