> For the complete documentation index, see [llms.txt](https://pshizhsysu.gitbook.io/docker/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://pshizhsysu.gitbook.io/docker/registry/api/pushjing-xiang.md).

# 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-v1`与`schema2-v2`。在这里，我们只能上传`schema2-v1`格式的manifest。

（未完待续）
