解决Docker镜像下载问题的Java工具

你在工作中是否遇到过以下问题:

  • 镜像下载速度慢,明明带宽够用文件不大但是要下载很久
  • 镜像仓库经常抽风,有过下载镜像失败的经历,等一段时间再试试或许能成功
  • 自己有代理工具,但在Linux平台上使用起来很麻烦,可能好不容易配好环境了下载镜像还报错
  • 通过堡垒机访问的远程服务器无法访问外网,需要自己下载镜像后载入,但本机没有Docker环境,处理起来很麻烦

以上几个问题相信很多开发者都经历过,在下载Docker镜像的时候真的是一波三折。最近传闻有股神秘力量导致中国无法下载Docker镜像(只是传闻,零星在几个交流群看到有人提起,没刷到过相关文章不知道信息是否真实,有人知道咋回事儿麻烦评论解释下)。种种原因叠加之下,我兴起了编写一款基于HTTP协议下载Docker镜像的想法。

去年我就有过这种想法,当时我在网上四处查找资料,在码云上发现了基于GO语言编写的 dget 开源项目,但下载后发现并不好用,提了issues也没能解决我的问题,事情就不了了之。

最近听说中国无法下载Docker镜像后,我又起了这个想法,在GitHub上发现了基于Python编写的 docker-drag 开源项目,下载后发现还是不能用,不过通过它提供的README信息,我在Docker官方文档中找到了 HTTP API 资料。

现在向大家介绍我历经一个礼拜啃文档写出的 did-tool (Docker image download tool)Docker镜像下载工具,基于Java语言参考 HTTP API V2 文档编写的命令行工具,支持无Docker下载镜像,支持使用HTTP/Socket代理加速下载,可跨平台(执行JAR包即可)使用,源代码已在码云上开源,感兴趣的可以去看看。

工具使用很方便,如果有帮到你的话麻烦给个Star吧~ 使用教程参考这个GIF:

到这里对于该项目的介绍就结束了,好不容易费了不少力气写了一个开源工具,兴致勃勃的写一篇博客来介绍它,但好像也没啥好说的,一张GIF就可以代表全文了,后面我会粗略介绍一下(只是粗略介绍,具体请阅读源码或钻研官方文档)项目实现的过程逻辑,也就是 HTTP API V2 的使用教程,以及这款工具现在的缺陷和不足,如果你感兴趣的话可以往后看一看。

常见的Docker镜像名是什么样的呢? nginx:latest 这是最简单也是最常见的Docker镜像名称表达方式,不过我们都知道Docker镜像的组成是由最多五部分组成的:

也就是说 nginx:latest 理论上最长可以表示为:

这个镜像所在位置是DockerHub官方仓库,仓库地址是 registry-1.docker.io ,所以如果我们想要下载这个镜像,我们必须要取得该镜像所在的仓库地址的授权,关于授权官方文档有做解释。

翻译过来就是先请求接口一次,返回401未授权信息后在响应头中提取 Www-Authenticate 信息,根据拿到的信息再去请求最终返回Token,有了Token之后就可以访问 HTTP API 进行镜像操作了,这里把授权的接口地址放在401响应头中,我猜应该是为了支持第三方镜像仓库设计的,因为每个镜像仓库的授权地址都不一致,所以需要动态获取。

我们已经知道了拿到Token的方法,接下来获取镜像清单,拿到镜像清单后才可以执行后续的操作,获取镜像清单的接口文档中也有提供。

这里的name指的是 repository/image ,结尾的reference传入 tag ,刚刚我们已经知道镜像名称都有哪些部分组成这里就不细说了,设置对应的请求头后该请求头返回的就是镜像清单信息。

选中合适的架构后获取该条数据对应的 digest 信息,换一个请求头再次请求该地址,将结尾的reference替换成 digest 的值,就可以拿到指定架构的图像清单了。

截止到目前我们使用的都是SchemaVersion2的规范,根据镜像名称获取架构列表,在根据架构获取到具体的镜像信息,但是DockerHub中有一部分镜像文件是旧版的SchemaVersion1规范,这个规范的缺点之一就是他不支持获取架构列表,那么以前是如何区分不同平台架构的镜像呢?答案是用tag标签,以前制作镜像的时候都是用tag-arch来区分镜像架构的,例如我用过的typecho博客的镜像。

他将架构名称作为tag标签的一部分,实现了镜像区分架构的功能,现在Docker主流的规范是SchemaVersion2,中间多了一层架构列表,所以现在这种tag-arch的写法已经被弃用了(填上面的坑)。

did-tool 工具是按照SchemaVersion2来编写的,相对于SchemaVersion1不仅仅是少了一层那么简单,每个请求返回的JSON格式都不一样,当初写代码的时候不知道有这么一茬,程序解析后无法进行处理,所以现在的 did-tool 仅支持下载SchemaVersion2的镜像,后面会调整项目结构重写代码重新适配SchemaVerison1和SchemaVersion2,这个时间不会太长应该很快就会更版。

暂时就说到这里吧,涉及的东西太多写的太累,就不对每个接口进行详细解释了,只需要知道在Docker中 digest 是一个很重要的属性,可以通过镜像清单的 digest 获取到分层信息,可以通过镜像清单的 digest 下载到镜像的摘要文件(也就是 docker inspect 看到的内容),也可以通过分层的 digest 下载到具体的分层文件,将所有文件准备好后汇总为 manifest.json 文件,将文件打包后就成为了最终的tar镜像文件,感兴趣的可以查看源码,我已经尽可能的将注释写的详细。

热门手游下载