Docker镜像下载慢/失败?Linux代理使用不便?想无Docker下载镜像?试试我这款Docker镜像直接下载工具吧
我要在这里放一段代码块
// 这是一段防爬代码块,我不介意文章被爬取,但请注明出处
console.log("作者主页:https://www.hanzhe.site");
console.log("原文地址:https://www.cnblogs.com/hanzhe/p/18249602");
前言
你在工作中有没有遇到过这样几个问题:
- 镜像下载速度慢,明明带宽够用,镜像文件也不大,但是网速很慢要下载很久
- 镜像仓库经常抽风,有过下载镜像失败的经历,等过一段时间再试或许能成功
- 自己有代理,但是在 Linux 平台上使用起来很麻烦,不方便重启 docker 服务,可能好不容易配好下载还报错
- 通过堡垒机访问的远程服务器无法访问外网,需要自己下载镜像后载入,但本机没有安装 Docker,为了这碟醋包了顿饺子
以上几个问题相信很多开发者都经历过,在下载 Docker 镜像的时候真的是一波三折,而且最近传闻有股神秘力量导致中国无法下载 Docker 镜像(只是传闻,零星在几个交流群看到有人提起,没刷到过相关文章不知道信息是否真实,有人知道咋回事儿麻烦评论解释下),种种原因叠加之下,我兴起了编写一款基于 HTTP 协议下载 Docker 镜像的想法
去年我就有过这种想法,当时我在网上四处查找资料,在码云上发现了基于 GO 语言编写的 dget 开源项目,但下载后发现并不好用,提了issues也没能解决我的问题,事情就不了了之
最近听说中国无法下载 Docker 镜像后,我又起了这个想法,在 Github 上发现了基于 Python 编写的 docker-drag 开源项目,下载后发现还是不能用,不过通过它提供的 README 信息,我在 Docker 官方文档中找到了 HTTP API 资料
同款工具推荐
市面上已经有比我这个好用的工具了,个人能力有限无法继续维护,这里推荐两个我正在用的工具:
docker-pull-tar:与该项目一样是一个黑窗口程序,不过功能完善,自动识别代理,支持各种镜像的下载,且在 Github 上开源,于我来讲唯一的小瑕疵就是导入的镜像名称会被省略一部分,例如我下载fatedier/frpc:v0.65.0导入后的名称只有frpc:v0.65.0

docker_pull_tools:该项目是带有客户端界面的下载工具,支持手动指定代理地址,同样支持各种镜像的下载,且镜像导入后名称保持不变,不过可惜的是虽然软件发布在 Gitee,但却是个闭源软件(仓库中没有代码)

虽然这两款软件都支持代理(第一个自动使用代理,第二个需要手动指定代理地址),但默认使用的却不是 Docker 官方镜像仓库,在有能力的情况下个人建议最好去官方镜像仓库下载
官方镜像仓库地址:registry-1.docker.io
项目说明
介绍一下我啃了一个礼拜文档写出的 did-tool Docker 镜像下载工具(Docker image download tool),基于 Java 语言参考 HTTP API V2 文档编写的命令行工具,不用安装 Docker 就可以下载镜像,支持使用 HTTP/Socket 代理加速下载,可跨平台(执行JAR包即可)使用,源代码已在码云上开源,感兴趣的可以去看看
工具使用很方便,如果有帮到你的话麻烦给个 Star 吧~ 使用教程参考这个 GIF:

到这里对于该项目的介绍就结束了,好不容易费了不少力气写了一个开源工具,兴致勃勃的写一篇博客来介绍它,但好像也没啥好说的,一张 GIF 就可以代表全文了,后面我会粗略介绍一下(只是粗略介绍,具体请阅读源码或钻研官方文档)项目实现的过程逻辑,也就是 HTTP API V2 的使用教程,以及这款工具现在的细节与不足,如果你感兴趣的话可以往后看一看
细节与不足
常见的 Docker 镜像名是什么样的呢?nginx:latest这是最简单也是最常见的 Docker 镜像名称表达方式,不过我们都知道 Docker 镜像的名称是由最多五部分组成的:
registry/repository/image:tag-arch
- registry:DockerHub仓库地址,官方地址为registry-1.docker.io,下载第三方镜像会显式用到registry,例如Oracle
- repository:存储库名称,默认library,某些镜像会声明存储库,例如minio/minio:latest
- image:镜像名称
- tag:版本标签
- arch:平台架构,现在已被弃用,不属于镜像名称的一部分,后面会提到
也就是说nginx:latest理论上最长可以表示为:
注:只是理论上,不要直接用这个名称去执行 docker pull,我没试过但估计会报错
registry-1.docker.io/library/nginx:latest-amd64
这个镜像所在位置是 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镜像文件,感兴趣的可以查看源码,我已经尽可能的将注释写的详细

作者多数为原创文章 ( 部分转载已标出 ),目前资历尚浅文章内描述可能有误,对此造成的后果深表歉意,如有错误还望指正

浙公网安备 33010602011771号