镜像如何推送到Harbor

2022-06-24

1. Harbor架构图

Harbor架构图

可以看到,harbor直接用了第三方组件Docker distribution作为自己镜像存储的服务端:
https://github.com/distribution/distribution

2. 推送镜像主要流程

Docker distribution的doc文档里做了详细的说明:https://github.com/distribution/distribution/blob/main/docs/spec/api.md#pushing-an-image
或查看Docker文档网站:https://docs.docker.com/registry/spec/api/#pushing-an-image

2.1 Pushing a Layer

使用两个步骤来管理上传过程。第一个步骤在注册表服务中开始上传,并返回一个网址来执行第二步.。第二步使用上传的网址来传输实际数据。上传是通过POST请求开始的,它返回一个网址,可以用来推送数据和检查上传状态。

2.1.1 Starting An Upload

开启一个镜像上传请求

POST /v2/<name>/blobs/uploads/

对于云音乐的业务镜像来说,name格式形如:music-homepage-home/music-homepage-home-dg

2.1.2 Existing Layers

客户端发出请求判断HEAD请求检测层是否已存在

HEAD /v2/<name>/blobs/<digest>

2.1.3 Uploading the Layer

Monolithic Upload 单层上传,不分片。一次性上传整个层。用PUT请求

PUT /v2/<name>/blobs/uploads/<uuid>?digest=<digest>
Content-Length: <size of layer>
Content-Type: application/octet-stream

<Layer Binary Data>

Chunked Upload 块上传。用PATCH请求 (常见的都是这种上传方式)
重点在于header:Content-Range,用于标识此次分片的起始位置

PATCH /v2/<name>/blobs/uploads/<uuid>
Content-Length: <size of chunk>
Content-Range: <start of range>-<end of range>
Content-Type: application/octet-stream

<Layer Chunk Binary Data>

注意:这里并不是分片上传,而是同步的按顺序的一块一块的上传,为什么这样做,好像和压缩也需要时间有关系?

2.1.4 Completed Upload

用一个PUT请求告诉服务端整个layer的上传已经结束

PUT /v2/<name>/blobs/uploads/<uuid>?digest=<digest>
Content-Length: <size of chunk>
Content-Range: <start of range>-<end of range>
Content-Type: application/octet-stream

<Last Layer Chunk Binary Data>

注意:这最后一次也可以选择性的传最后一块chunk

2.2 Pushing an Image Manifest

镜像层全部上传完成后,客户端可以上传镜像清单

PUT /v2/<name>/manifests/<reference>
Content-Type: <manifest media type>

{
    "name": <name>,
    "tag": <tag>,
    "fsLayers": [
        {
          "blobSum": <digest>
        },
        ...
    ]
    "history": <v1 images>,
    "signature": <JWS>,
    ...
}