6

将镜像tar包通过API直接push到registry仓库

 3 years ago
source link: https://silenceper.com/blog/202007/docker-tar-push/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

为了实现docker tar包能够直接通过页面上传,调研了一下registry的api,以及如何解析tar包(其实就是docker daemon程序实现的部分)。

要想实现,首先要了解docker tar包中结构组成:

tar包结构

拿了一个包含一个镜像的tar包进行解压:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.
├── 1ecf8bc84a7c3d60c0a6bbdd294f12a6b0e17a8269616fc9bdbedd926f74f50c
│   ├── VERSION
│   ├── json
│   └── layer.tar
├── 6f4ec1f3d7ea33646d491a705f94442f5a706e9ac9acbca22fa9b117094eb720.json
├── aaac5bde2c2bcb6cc28b1e6d3f29fe13efce6d6b669300cc2c6bfab96b942af4
│   ├── VERSION
│   ├── json
│   └── layer.tar
├── b63363f0d2ac8b3dca6f903bb5a7301bf497b1e5be8dc4f57a14e4dc649ef9bb
│   ├── VERSION
│   ├── json
│   └── layer.tar
├── c453224a84b8318b0a09a83052314dd876899d3a1a1cf2379e74bba410415059
│   ├── VERSION
│   ├── json
│   └── layer.tar
├── dd8ef1d42fbcccc87927eee94e57519c401b84437b98fcf35505fb6b7267a375
│   ├── VERSION
│   ├── json
│   └── layer.tar
├── manifest.json
└── repositories

文件说明:

manifest.json文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[
    {
        "Config":"6f4ec1f3d7ea33646d491a705f94442f5a706e9ac9acbca22fa9b117094eb720.json",
        "RepoTags":[
            "alpine:filebeat-6.8.7-arm64"
        ],
        "Layers":[
            "aaac5bde2c2bcb6cc28b1e6d3f29fe13efce6d6b669300cc2c6bfab96b942af4/layer.tar",
            "dd8ef1d42fbcccc87927eee94e57519c401b84437b98fcf35505fb6b7267a375/layer.tar",
            "c453224a84b8318b0a09a83052314dd876899d3a1a1cf2379e74bba410415059/layer.tar",
            "b63363f0d2ac8b3dca6f903bb5a7301bf497b1e5be8dc4f57a14e4dc649ef9bb/layer.tar",
            "1ecf8bc84a7c3d60c0a6bbdd294f12a6b0e17a8269616fc9bdbedd926f74f50c/layer.tar"
        ]
    }
]

manifest.json 包含了对这个tar包的描述信息,比如image config文件地址,tags说明,镜像layer信息,在解析的时候也是根据这个文件去获取关联的文件。

image config文件

比如:6f4ec1f3d7ea33646d491a705f94442f5a706e9ac9acbca22fa9b117094eb720.json文件:

内容太多就不贴了 这里包含了镜像运行的信息,比如env,执行参数,以及镜像历史等。

layer层文件:layer.tar

镜像的每一层的文件信息都打包在了一个单独的layer.tar包中,也是在上传的时候需要用到的。

registry api

流程:

  • 1、获取鉴权信息
  • 2、检查layer.tar是否已经存在
  • 3、上传layer.tar
  • 4、上传image config
  • 5、上传manifest(非包中的manifest.json而是Manifest struct

这里只列出了在上传的时候需要用的api

1、获取鉴权信息

这里跟registry仓库选择的鉴权方式有关,可选basic auth或者token鉴权。 这里我是以最基本的basic auth为例子,如果是token鉴权的方式参考这里: https://docs.docker.com/registry/spec/auth/jwt/

2、检查上传

1
HEAD /v2/image/blobs/<digest>

若返回200 OK 则表示存在,不用上传

3、开始上传服务 我这里是以分块上传的方式进行

1
POST /v2/image/blobs/uploads/

如果post请求返回202 accepted,一个url会在location字段返回.

     202 Accepted
     Location: /v2/\<image>/blobs/uploads/\<uuid>
     Range: bytes=0-<offset>
     Content-Length: 0
     Docker-Upload-UUID: <uuid> # 可以用来查看上传状态和实现断点续传

4、分块上传 根据上一步获取的url,以PATCH的方式提交分块数据。 如果是最后一块数据上传,则以PUT的方式提交,如下:

 > PUT /v2/<name>/blob/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>

上传layer,image config,manifests信息都是一样的。

我暂时只用到了以上api,更多的api参考:https://docs.docker.com/registry/spec/api/

上面说API没啥感觉,还是看代码比较明白,所以实现了这么一个工具:https://github.com/silenceper/docker-tar-push

Usage:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
push your docker tar archive image without docker.

Usage:
  docker-tar-push [flags]

Flags:
  -h, --help              help for docker-tar-push
      --log-level int     log-level, 0:Fatal,1:Error,2:Warn,3:Info,4:Debug (default 3)
      --password string   registry auth password
      --registry string   registry url
      --skip-ssl-verify   skip ssl verify
      --username string   registry auth username

Example:

1
docker-tar-push alpine:latest --registry=http://localhost:5000

参考


search_study_program.png
关注公众号,获取最新文章推送

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK