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里面是目录,也不知道原来的服务器是不是啥时候删除过目录改了文件。
不过,最后不纠结,用上面的两步,利用新文件映射过去就好了。