浅析Dockerhub API:如何优雅地从dockerhub偷rootfs镜像
成品:
https://github.com/Moe-hacker/docker_image_puller
前言:
八月初的时候,咱无聊去扒了下dockerhub的接口,想通过网络请求直接从dockerhub偷镜像。
然后写完才想起来dockkerhub在国内是被墙的,似乎这么一个功能用处也不大。。。。。
然后咱就去旅游了,连项目Readme都没写(逃)。
至于现在为啥写这篇文章,因为上课摸鱼。。。
前置函数:
1 | def panic(message): |
关于image字段:
除了docker search的实现之外,其他如果不带repo前缀的默认需要在image字段加入library/前缀,比如ubuntu镜像的image字段应该是library/ubuntu。
镜像查找:
首先是镜像的查找,也就是docker search的实现。
这个接口十分简单,需要两个参数:要查找的字段(image)和获取内容的条数(page_size)。
1 | response = requests.get("https://hub.docker.com/v2/search/repositories/?page_size=" + str(page_size) + "&query=" + image) |
设image=”ubuntu”, page_size=1, 在response.text中你会获得一段这样的json:
1 | { |
所以我们直接解析json输出就好了。
1 | response = json.loads(response.text) |
输出如下:
1 | ubuntu [official] |
然后是tag的查找,这个API和上面差不多, 给出镜像名image和数据条数page_size:
1 | response = requests.get("https://hub.docker.com/v2/repositories/" + image + "/tags/?page_size=" + str(page_size)) |
设image=”library/ubuntu”, page_size=1, 在response.text中你会获得一段这样的json:
1 | { |
这里解析复杂一点,需要results:images:architecture和主机架构一致:
1 | if response.status_code != 200: |
输出如下:
1 | [ubuntu] latest |
rootfs获取:
这里超级坑,步骤有点多我们慢慢来:
获取token:
虽然不知道为什么,但我们在获取docker镜像前需要先申请一个token,服务器在后续请求时需要验证你的token。
我们只需要提供镜像名image,就是上面docker search出来的那个名字
1 | response = requests.get( |
我们会获得这样一段json:
1 | { |
我们只需要token就行了:
1 | response = json.loads(response.text) |
然后我们开始获取镜像。
首先获得镜像image标签tag对应的信息,这一步需要token:
1 | response = requests.get("https://registry-1.docker.io/v2/" + image + "/manifests/" + tag, |
image=”library/ubuntu”,tag=”latest”你将获得如下json:
1 | { |
解析获得和主机架构对应的digest:
1 | if response.status_code != 200: |
最后我们解析这个digest,获得最终要下载的文件, 需要image,digest和token:
1 | response = requests.get("https://registry-1.docker.io/v2/" + image + "/manifests/" + digest, |
你将获得:
1 | { |
获取layers字段的digest:
1 | if response.status_code != 200: |
最后下载下来解压:
需要image, blobs(上面的ret), token, 保存路径savedir:
1 | os.system("mkdir " + savedir) |
最后,有些docker镜像启动命令并非默认,我们可以解析config来获得它:
1 | def get_cmd(image, digest, token): |
config的json长这样:
1 | { |
结尾:
EOF