前言
docker
用了这么久了, 有没有想过, 在执行docker push
和 docker pull
命令的时候, 数据是如何传递的呢? 换句话说, 如果要实现一个镜像仓库, 针对推拉的服务, 如何实现接口呢?
根据OCI 分发规范文档 的描述, 已经对整个推拉过程中要调用的接口有描述了. 但是, 纸上学来终觉浅, 我还是决定针对harbor
仓库进行推拉操作的抓包, 看看实际上接口调用是怎样的.
以下所有抓包, 均为本地搭建的 harbor
仓库(在实现上可能与OCI 略有差异).
pull
执行命令: docker pull hub.hujingnb.com:8090/library/alpine:2.6
抓包结果如下(层在本地没有, 需要下载):
根据OCI
文档对流程进行说明(第1个请求用于建立连接, 跳过):
METHOD | 接口 | 说明 | OCI 对应 |
---|---|---|---|
GET | /v2 | 尝试获取仓库的API 版本. 此接口在响应头中标记了获取权限的地址: Www-Authenticate Bearer realm="http://hub.hujingnb.com:8090/service/token",service="harbor-registry" |
|
GET | /service/token | 根据上一步提供的地址, 获取访问令牌 | |
HEAD | /v2/library/alpine/manifests/2.6 | 从这一步开始拉取镜像. 检查镜像是否存在, 若不存在返回状态码404 . 若存在, 同时将镜像的哈希返回到响应头中: Docker-Content-Digest sha256:5c4217c00be9ecba7735157998a4ac0475b5381c8c885396baa6f798f7f839db |
/v2/<name>/manifests/<reference> |
GET | /v2/library/alpine/manifests/sha256:5c42... | 获取镜像的manifests 信息 |
/v2/<name>/manifests/<reference> |
GET | /v2/library/alpine/blobs/sha256:c954... | 根据上一步拿到的镜像结果, 下载各个层信息 (在这一步会校验, 若层在本地已经存在, 则跳过下载) | /v2/<name>/blobs/<digest> |
通过以上接口调用, 就已经拿到了一个镜像的所有信息.
push
执行命令: docker push hub.hujingnb.com:8090/library/alpine:3.1
抓包结果:
根据OCI
文档对流程进行说明(第1个请求用于建立连接, 跳过):
METHOD | 接口 | 说明 | OCI 对应 |
---|---|---|---|
GET | /v2 | 同上 | |
GET | /service/token | 同上 | |
HEAD | /v2/library/alpine/blobs/sha256:0f25... | 判断层是否存在. 若在远端不存在, 则返回404 | /v2/<name>/blobs/<digest> |
POST | /v2/library/alpine/blobs/uploads/ | 开始一次层上传. 响应202成功, 在响应头的Location 字段标明上传地址 |
/v2/<name>/blobs/uploads |
PATCH | /v2/library/alpine/blobs/uploads/6c82... | 使用上一步返回的Location 地址执行上传任务, 分片上传 |
/v2/<name>/blobs/uploads/<reference> |
PUT | /v2/library/alpine/blobs/uploads/6c82... | 标识本次上传完毕 | /v2/<name>/blobs/uploads/<reference> |
HEAD | /v2/library/alpine/blobs/sha256:0f25... | 在层上传完毕后, 再次调用接口检查是否上传成功. 返回200说明存在 | /v2/<name>/blobs/<digest> |
... | ... | 重复操作上传所有层 | |
PUT | /v2/library/alpine/manifests/3.1 | 所有层上传完毕, 推送镜像manifests 信息 |
/v2/<name>/manifests/<reference> |
以上, 一个镜像就成功的推送到镜像仓库了. 推送基本上就是把pull
的操作反过来.
其他
更具体的, 可以查看OCI 分发规范, 拢共也没多少, 可以通读一遍. 在这个位置 定义了一些接口规范, 可以看一下.
对于仓库的实现, 可以查看harbor 源码, 也可以查看distribution 来了解其实现.
其实整个看下来, 倒也不觉得神秘了, 无非就是一些数据的上传, 全部使用HTTP
协议, 散会