push镜像

流程

镜像上传的流程与下载刚好相反。上传的时候先上传layer,然后再上传manifests文件。

上传layer

上传初始化

在上传每一个layer之前,先要调用一个api进行layer上传的初始始化操作,

POST /v2/<repository>/blobs/uploads

该API调用会返回一个结果,告诉我们接下来如何去上传这一个layer,比如:

$ curl -X POST -I 192.168.1.103:8021/v2/library/registry/blobs/uploads/
HTTP/1.1 202 Accepted
Server: nginx/1.11.5
Date: Thu, 13 Sep 2018 11:05:26 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 0
Connection: keep-alive
Docker-Distribution-Api-Version: registry/2.0
Docker-Upload-Uuid: 91cbb0a1-c335-45ae-b155-86bf06897d9d
Location: http://192.168.1.103:8021/v2/library/registry/blobs/uploads/91cbb0a1-c335-45ae-b155-86bf06897d9d?_state=YeQZM_9WTPi9Gxfgi6chPo7gZ0fRsJisqthEwHrrmTl7Ik5hbWUiOiJsaWJyYXJ5L3JlZ2lzdHJ5IiwiVVVJRCI6IjkxY2JiMGExLWMzMzUtNDVhZS1iMTU1LTg2YmYwNjg5N2Q5ZCIsIk9mZnNldCI6MCwiU3RhcnRlZEF0IjoiMjAxOC0wOS0xM1QxMTowNToyNi45NzI2MjE4ODhaIn0%3D
Range: 0-0

在返回结果中有一个Location字段,该字段表示上传该layer的URL。

整块上传

我们调用拿到上面的URL后,就可以上传实际的layer了。上传layer时可以把layer切成多块,分多个http请求上传,也可以在一个http请求中上传。接下来,我们一次性把整个layer都上传:

$ curl -X PUT -H "Content-Type: application/octet-stream" -H -I --upload-file /root/image/layers/06ba8e23299fcf9dd9efb3c5acd4c9d03badac5392953001c75d38197113a63a.tar.gz http://192.168.1.103:8021/v2/library/registry/blobs/uploads/91cbb0a1-c335-45ae-b155-86bf06897d9d?_state=YeQZM_9WTPi9Gxfgi6chPo7gZ0fRsJisqthEwHrrmTl7Ik5hbWUiOiJsaWJyYXJ5L3JlZ2lzdHJ5IiwiVVVJRCI6IjkxY2JiMGExLWMzMzUtNDVhZS1iMTU1LTg2YmYwNjg5N2Q5ZCIsIk9mZnNldCI6MCwiU3RhcnRlZEF0IjoiMjAxOC0wOS0xM1QxMTowNToyNi45NzI2MjE4ODhaIn0%3D\&digest=sha256:06ba8e23299fcf9dd9efb3c5acd4c9d03badac5392953001c75d38197113a63a
HTTP/1.1 100 Continue

HTTP/1.1 201 Created
Server: nginx/1.11.5
Date: Thu, 13 Sep 2018 11:12:30 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 0
Connection: keep-alive
Docker-Content-Digest: sha256:06ba8e23299fcf9dd9efb3c5acd4c9d03badac5392953001c75d38197113a63a
Docker-Distribution-Api-Version: registry/2.0
Location: http://192.168.1.103:8021/v2/library/registry/blobs/sha256:06ba8e23299fcf9dd9efb3c5acd4c9d03badac5392953001c75d38197113a63a

当上传成功后,会返回状态码201,表示该layer已经上传成功。

其他layer

其他layer的上传重复上面的两个请求即可

避免layer的重复上传

registry有两个API

HEAD /v2/<repository>/blobs/<digest>
POST /v2/<repository>/blobs/uploads/?mount=<digest>&from=<repositoryName>

第一个API可以判断该repository下某个layer是否已经存在,第二个API可以从registry中的另一个repository将某个layer挂载过来。但是,对于第二个API,该请求必须对于

对于docker-daemon,其默认行为是会调用第一个API,不会调用第二个(因为docker-daemon不知道registry上有哪些其他的repository)。所以,当docker push在上传镜像的时候,如果一个repository有两个tag,那么上传第二个tag时,重复的layer就不会上传。但如果两个镜像的repository不一样,那么即使它们有重复的layer,也会各自上传一次。

上传manifest文件

manifest文件有两种格式,schema2-v1schema2-v2。在这里,我们只能上传schema2-v1格式的manifest。

(未完待续)

Last updated