Docker镜像本地拉取与迁移
由于网络连通性原因,DockerHub的访问变得困难。然而在服务器上部署服务时,又经常需要使用Docker。
为了避免在服务器上进行复杂的网络设置,一种相对折中的方法是:在一台网络流畅(下面称为本机)的机器上获取Docker镜像,再将镜像复制到服务器上使用。
工具 - Skopeo
一种传统的方法是,在本机上也安装一个Docker
Engine,使用docker pull
命令拉取镜像,再使用docker save
导出镜像。
这种方法的缺点在于,我们在本机上或许并不需要/不想要/难以安装Docker引擎。
而维新派指出,在Docker引擎官方代码仓库moby/moby/contrib下,有一个download-frozen-image-v2.sh脚本,该脚本提供了对Docker镜像的下载功能。听起来不错?
而当然,也有更便捷的工具:containers/skopeo。这也是本文介绍的主角。
安装Skopeo
安装skopeo相当简单,例如在Debian 11+/Ubuntu 20.10+内,可以直接在apt源中下载安装。Alpine Linux同样可以使用apk直接添加。
尽管skopeo不支持Windows版本,但完全可以创建一个简易的Alpine Linux WSL环境完成以上任务。
使用Skopeo获取镜像
主要使用的是skopeo copy
命令,文档参见skopeo/docs/skopeo-copy.1.md。
具体来说,在拷贝时,我们常常希望把镜像打成一个tar
包,可以方便地在网络上传输。skopeo可以直接导出tar
文件,具体如下:
1 | skopeo copy docker://<image>:<tag> docker-archive:/path/to/archive.tar:<image>:<tag> |
例如,如果想要拉取busybox的最新版本镜像busybox:latest
,可以执行:
1 | skopeo copy docker://busybox:latest docker-archive:myarchive.tar:busybox:latest |
如果镜像是由非Docker官方发布的,镜像名称中会含有斜杠,请放心,此时镜像名称<image>
就是包含斜杠的完整字符串。例如,以下命令当然是没问题的。
1 | skopeo copy docker://bitnami/postgresql:14 docker-archive:/path/to/archive.tar:bitnami/postgresql:14 |
值得注意的是,在上述命令里,附加在打包文件名后的<image>:<tag>
,即为之后导入docker时,该镜像所关联到的名称。
例如,如果执行:
1 | skopeo copy docker://busybox:latest docker-archive:myarchive.tar:busybox:10086 |
导入到docker中的镜像名称也会被显示为busybox:10086
:
1 | user@server:~$ docker images |
打包后,为了节约传输带宽和时间,可以对打包好的tar
文件压缩一下。可以使用zstd
(gz
等当然也行),大约能缩小2/3的体积。
1 | zstd -9 myarchive.tar |
在服务器上导入镜像
使用喜欢的方法将打包文件传输到服务器后,就可以导入Docker引擎:
1 | docker load < myarchive.tar.zstd |
这里使用的是重定向输入文件流,当然也可以使用-i
参数引导读取指定路径的文件。同时,docker load
也可以加载包括gz
,
xz
, bzip2
,
zstd
在内的压缩文件。
与同名同tag现有镜像的冲突
导入时会覆盖掉同名镜像,即原有镜像的名称会被置空,变成孤立的镜像。运行docker images prune
可以删除这些孤立镜像。