1

本文不讨论有关于 Docker 的问题,只说镜像。

镜像(知道怎么导出镜像就请跳过)

对于 Docker 来说,镜像一般是拉下来的,像这样:

docker pull trinodb/trino

但是,并非所有目标机器都是可连互联网的,这时候就需要像移动离线包一样去移动镜像。

在 Docker 里,一般的操作是,先导出镜像:

## save out
docker save docker.io/hello-world -o hello.tar
docker save docker.io/hello-world > hello.tar

Note

上面两种写法效果一样

然后挪到另一个已经安装了 Docker 的地方,导入:

## load in
docker load -i hello.tar
docker load < hello.tar

Note

上面两种写法效果一样

到这里,知道 tar 格式一般用来干啥的朋友们,应该就能清楚,这里 Docker 的这种设计是怎么一个想法了。

不清楚没关系,我告诉你。

压缩 tar 一般的作用就是:

  • 把多个文件打包成单个文件,且没有压缩
  • 保留文件原来的样子,比如软链接被打包又解包后还是软链接(可以自己试试直接用压缩命令比如 xz 啥的压一个软链接再解压)(当然 tar 也可以选择不保留即比如让软链接变成文件本体)。

Note

如果你是 Windows 用户,那么 WinRAR 这个软件你肯定用过,它里面有一个选项是 保留软链接 ,其实是差不多的意思。在 Linux 上的习惯,是打包和压缩分成两部分,可以单独做也可以同时做(同时做依靠管道),由不同的软件来做,从而严谨的压缩结果名字就是 xxx.tar.xz 这种(当然其实命名是随便的都能用(是否需要严谨自己视自己情况));而在 WinRAR 相当于两部分合并为一部分了,压缩结果对应就是 xxx.rar

那么这里 Docker 只支持导出 tar 文件(无所谓你重定向为啥名字它都是一个 tar 包的不信可以自己想办法检查一下)的用意就是:

  • 就是让你自由地选择用那种压缩格式压缩或者干脆不压缩。同时,这些压缩算法和 Docker 本身是完全独立的(你更新不牵扯我我更新不牵扯你而且互相可以换成别的替代品)。

那么:

加入压缩!

压缩

压缩的话,本文会提到 xzzstd 这两个压缩工具。它们的算法都不错。

先看一般场景,再用到 Docker 上。

一般场景

xz 好处是一般来说压缩率最好,但速度相对另一个慢不少。我用 xz 一般用最高压缩,经常会好过 7-zip 的压缩效果。

压缩解压缩示例:

## compress
tar cf - * | xz -T0 --best > pkged.tar.xz

## decompress
xz -d pkged.tar.xz --stdout | tar -x
tar xJf pkged.txz

Note

上面的解压两种写法都行

  • [ ] 待补充 ZSTD 一般使用

在 Docker 上

这样可以在 Docker 上导出的同时直接顺便压缩。以及一键解压载入。

## save out
docker save docker.io/hello-world | xz -T0 --best > hello.tar.xz

## load in
xz -d hello.tar.xz --stdout | docker load
xz -d hello.tar.xz --stdout | docker load < /dev/stdin
xz -d hello.tar.xz --stdout | docker load -i /dev/stdin

Note

注意不要对管道 | 前面部分命令增加 -o /dev/stdout 或者 > /dev/stdout ,会导致压缩失败。

另外,加载那三行都可以用。建议用第一行那个就行。

  • [ ] 待补充 ZSTD 与 DOCKER 互动

远程传输

众所周知,有个命令叫 rsync

不知道?那下面就让你知道。知道它的 -az 选项的话可以跳过了。

Note

如果你能连上比如 101.202.103.204 这个机器,你还想和它来回传文件,你又知道这个机器上有个用户叫 heiheihei 以及这个奇怪用户的密码,你就可以像这样:

  • rsync -avz heiheihei@101.202.103.204:远方的某张图.png . 这样就把这个机器的 heiheihei 用户的初始目录里的 远方的某张图.png 这个文件, 101.202.103.204 从拉到了你本机的当前目录 . ,并且修改时间啊之类的都没变。它的传输途中还经过了一个简单的压缩,算法好像是 GZIP 吧。
  • 同理,你还可以吧你的某个文件怼给人家: rsync -avz ./自动下载不知该怎么描述的动图的脚本.sh heiheihei@101.202.103.204: ,如果 heiheihei 用户有权限对 /etc/profile.d 这个重要的目录写入些什么的话,每次用这个用户登录就都会被迫执行一些奇怪的命令了。(实际使用不建议瞎球乱搞这个目录里的东西
顺便,你以为 heiheihei 回家会大吃一惊吗?不,你就是 heiheihei

总之,像 rsync -az 的这种远程传输效果,在 Docker 可以直接实现吗?

  • 教练!我连 .tar.xz 这个文件也不想看到了!我想直接吧镜像从远处机器拉到本机!
  • 好!跟着我的姿势!我教你怎么拉!!

思路其实很简单:在 SSH 上直接执行命令,让原本要写入到 啥啥啥.tar.xz 里的内容直接输出到本机——但,不是输出到标准输出,那就乱七八糟一片了,也不必重定向成本地的某个文件,而是直接接管道就好。

看示例吧:

ssh 101.202.103.204 -- 'docker save docker.io/trinodb/trino | xz -T0 --best' | xz -dc | docker load

Note

引号里相当于是在远程执行的命令,只不过这个命令的 标准输出stdin ) 是怼给本机的。那么,本机直接进管道就是了,反正 xz -dc 就是读取标准输入并解压并把解压结果怼给标准输出。

这样一来,效果就是,载入了远端节点的某个已有镜像,然后中间传输还是压缩过后再传输的。

  • [ ] 待补充 ZSTD 做同样的事的代码
话说回来,不用文件名,这倒有点儿 Lambda 演算的风范呢。

分享注明来源: https://segmentfault.com/a/1190000040306956


awsr
13 声望0 粉丝