# 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。

（未完待续）


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://pshizhsysu.gitbook.io/docker/registry/api/pushjing-xiang.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
