3.4 推送容器镜像
- 解析镜像名称和标签:解析提供的镜像名称和标签,例如 registry-name/username/image:v1,未指定 registry-name 时,默认使用 docker.io。
- 推送镜像分层(Blob):
- Docker 会将镜像分解成多个层级,并逐层推送到镜像仓库
- 对于每一个镜像层:
- 首先检查镜像层是否存在:
HEAD /v2/<image>/blobs/<layer-digest> - 若镜像存在层存在则跳过,若不存在则先执行:
POST /v2/<image>/blobs/uploads/获取上传 URL,然后执行PATCH /v2/<image>/blobs/uploads/<upload-id>分片上传,或者使用PUT /v2/<image>/blobs/uploads/<upload-id>?digest=<layer-digest>整体上传
- 首先检查镜像层是否存在:
- 推送清单(Manifest): 当所有分层都上传完毕后,Docker 会将镜像的清单文件 (Manifest) 推送到镜像仓库:
PUT /v2/<image>/manifests/<tag>
访问 /v2/<images> 开头的接口都会一并发送调用 /v2/token 获取到的 Token 用于鉴权(如果本地有账号密码的话),如果遇到 Token 失效或者没有权限操作对应的镜像时,就会报错。
总得来说,先推送依赖项(blobs),再推送索引(manifest),在多架构镜像中也有类似情况,需要先推送单架构镜像的 manifest,再推送多架构镜像的 manifest.list。
我曾经在推送镜像时遇到过 HTTP 状态码 413 错误,提示 Request Entity Too Large,排查后发现客户的单层镜像高达 9.6GB,超过了公共镜像仓库的单层 2000MB 限制。
对于单架构镜像来说,每个镜像都是由多个镜像层组成的,docker 以及 registry 暂无镜像大小限制,而 Harbor 镜像大小的限制则有两处,一个是单层镜像大小不能超过 10GB,另一个则是可选配置的项目存储空间大小。 dockerhub 暂无镜像大小限制的明确说明,从网上的资料看也是限制单层 10GB,总计不超过 100GB。
过大的镜像层对推送镜像的操作来说并不友好,特别是请求经过反向代理的情况,如果使用 PUT 请求完整传输单层镜像,会需要占用大量的缓存空间。