Docker最漂亮的地方实际上就是,有一个Dockerfile或者利用yml文件,自动利用公有镜像,进行部署。
但是最近在一些公有镜像上做了一些改动,又不想发布出去,所以换服务器时就想着复制了。其实思路很简单,在源机器上save,在目标机上load。但考虑到懒,实现了一句话搞定。
先给大家一个整体思路:

docker stop NAME_OF_INSTANCE 
docker commit NAME_OF_INSTANCE mycontainerimage 
docker save mycontainerimage | gzip > mycontainerimage.tar.gz 

复制到目标机,再继续:

gunzip -c mycontainerimage.tar.gz | docker load 

但我们已经这么懒了,所以,自然是在一个服务器上搞定:
单行直接复制镜像,下面是在目标端,复制源端的镜像(实测过),如果这句话放在脚本里,要先ssh登陆过目标服务器,以便保持对应的key。否则会报错。因为没有机会输入yes。另外ssh端口为4122,不是默认的22,所以要单独指定一下。

ssh -p 4122 root@47.102.x.x 'docker save nuxt:latest | gzip' | gunzip |  docker load

这个是在源端推镜像到目标端

docker save mycontainerimage | gzip | ssh root@203.0.113.1 'gunzip | docker load' 

然后用自己的启动脚本运行呗:
结果出现了container init caused: rootfs_linux.go:59: mounting "/etc/timezone" 这类的报错无法启动。

docker: Error response from daemon: OCI runtime create failed: container_linux.go:346:
 starting container process caused "process_linux.go:449: container init caused 
\"rootfs_linux.go:58: mounting \\\"/etc/timezone\\\" to rootfs 
\\\"/var/lib/docker/overlay2/cb6229f54bfa2ffb1fdb70a316606bf5936ebe69c7d0ee8d26da98b78c9
1e857/merged\\\" at 
\\\"/var/lib/docker/overlay2/cb6229f54bfa2ffb1fdb70a316606bf5936ebe69c7d0ee8d26da98b78c9
1e857/merged/etc/timezone\\\" caused \\\"not a directory\\\"\"": unknown: Are you trying 
to mount a directory onto a file (or vice-versa)? Check if the specified host path 
exists and is the expected type

看着内容挺吓人的,找了一下回答说是服务器版本有不同,需要升级服务器的系统版本,或者降低docker版本等。就是做到统一。
但是自己阅读一下报错,其实是我点出的那句话,时区问题,我原有的docker启动脚本里有这样的参数

-v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime \
-v /etc/timezone:/etc/timezone \

第二行,出的问题,因为我复制的源使用的是Centos8,而本次的目标地是Centos7,8里面timezone是目录不是文件。
所以在命令行里执行如下,先做一个文件

echo 'Asia/Shanghai' > /etc/timezone/timezone

然后将复制的时区信息的文件指向上面生成这个文件即可。即
-v /etc/timezone/timezone:/etc/timezone \

第二次更换服务器时,发现代码里所有的timezone这一样实际上都是报错了,还是centos8到8,发现一样的服务器版本号,原来的8里面timezone是文件,新的8里面是目录,也不知道原来的服务器是不是啥时候删除过目录改了文件。
不过,最后不纠结,用上面的两步,利用新文件映射过去就好了。

Last modification:October 22, 2021
送杯咖啡,做个交流,谢谢!