51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Docker中Image、Container与Volume的迁移

Docker中Image、Container与Volume的迁移 第1张

已经部署的容器化服务,也不是不需要维护的。而且,由于生产环境往往有这样那样的严格要求,往往需要些非常规操作。Image(镜像)、Container(容器)和Volume(数据卷)的迁移,就是一类有用的非常规操作。

以下镜像,均以最简单的Alpine为例。

Image

镜像的迁移,适用于离线环境。

一般离线环境,都会自建Docker Registry。无论官方的,还是最近流行的Harbor,都是不错的选择。但是,这个世界上就是有些环境,或者说一些环境在某些时期,没有外网,也没有内部的Registry。这个时候要部署Docker的服务,怎么办?

只能通过镜像的迁移。实际上,Harbor的offline installer,就是采用这种形式。

Save

# use stdoutdocker save alpine > /tmp/alpine.tar# or write to a file directlydocker save alpine -o /tmp/alpine.tar

推荐使用-o的形式,因为利用stdout的做法虽然直观,但在某些场景下无效,比如利用ssh远程执行命令。

Load

# use stdoutdocker load < /tmp/wekan.tar# or read from a file directlydocker load -i /tmp/wekan.tar

Container

容器的迁移,适用于已经上线,且状态复杂、从零开始启动不能正常工作的服务。容器迁移的包,包含了镜像。


Export


先准备一个正在运行的服务,并且弄脏环境。


$ docker run --rm -d --name test alpine tail -f /dev/null9232f0c1dafe0f29918f281ca37bb41914677e818cb6f252abf3dab3be04fbb2$ docker exec test touch proof$ docker exec test ls -hl proof-rw-r--r--    1 root     root           0 Nov 20 14:33 proof

执行导出操作:


docker export test -o test.tar

Import


首先,关闭刚才运行的服务。


$ docker kill testtest

执行导入操作:


$ docker import test.tar test-imgsha256:e03727eeba7e16dd3acfcc7536f1244762508f9b6b9856e49cc837c1b7ffa444

要注意的是,import后得到的是一个镜像,相当于是执行了docker commit后的内容。当然,docker commit不是一个推荐的操作,所以容器的导入、导出,就显得不是那么的顺眼。

最后,检查之前创建的文件。



   
    $ docker run --rm -d --name test test-img tail -f /dev/nullee29cb63bb2d3ed8ac890789ba80c4fe4078b9d5343a8952b6217d64b4dcbe23$ docker exec test ls -hl proof-rw-r--r--    1 root     root           0 Nov 20 14:33 proof


   

  
   可以看到,前面创建的文件是存在的,并且时间戳完全一致。

  

Volume



Docker中Image、Container与Volume的迁移 第2张


数据卷的迁移,比较麻烦。Docker并未提供官方的简单方案。

当然,直接用root用户访问文件系统的Docker数据,比如默认的/var/lib/docker/volumes/下的文件夹,直接进行打包操作,也不是不行。但这毫无疑问是最糟糕的方案。

目前参考《Use volumes | Docker Documentation》,找到的最佳方案是,用另一个容器,把数据卷内容打包,并且通过挂载的形式传递到宿主机。

Backup


首先,准备一个Volume。

   
    $ docker run --rm -d --name test -v test-vol:/data test-img tail -f /dev/nullf4ff81f4c31025ff476fbebc2c779a915b43ba5940b5bcc42e3ef9b1379eaeab$ docker exec test touch /data/proof$ docker exec test ls -hl proof-rw-r--r--    1 root     root           0 Nov 20 14:40 proof


   

  
   执行备份操作:

  
$ docker run --rm -v test-vol:/volume -v $PWD:/backup alpine tar cvf /backup/backup.tar volumevolume/volume/proof

直接在已运行容器中打包,然后通过docker cp复制出来,也是一个方案。但这会对正在运行的容器有影响,不建议在真正重要的容器中使用。

这里利用了一个Alpine镜像来执行操作。实际上,任何一个自带tar的镜像都是可以的。

Restore


首先,清理刚才的容器和数据卷。


$ docker kill testtest$ docker volume rm test-voltest-vol

执行还原操作:


docker run --rm -v test-vol:/volume -v $PWD:/backup alpine tar xf /backup/backup.tar

最后,检查还原后的结果。


$ docker run --rm -v test-vol:/data alpine ls -ahl /datatotal 8drwxr-xr-x    2 root     root        4.0K Nov 20 14:48 .drwxr-xr-x    1 root     root        4.0K Nov 20 14:50 ..-rw-r--r--    1 root     root           0 Nov 20 14:40 proof

结论



以上三招六式,其实都不是常规手段。
Image的传递,更应该依赖于内部Docker Registry而非tar。(当然,也有例外,比如集群部署大镜像的P2P方案,也许可以借鉴这个手段。) Container的状态,应该是可弃的。一个运行了很长时间的Container,应该是可以restart、甚至kill后再重新run也不影响既有功能的。任何有依赖的状态,都应该考虑持久化、网络化,而不能单纯地保存在本地文件系统中。 Volume的手动迁移,的确可以采用上述方式。但是,Volume需要手动迁移、备份吗?这需要专业而完善的插件来实现。



往期精彩

《Docker是什么?》

《Kubernetes是什么?》

《Kubernetes和Docker到底有啥关系?》

《教你如何快捷的查询选择网络仓库镜像tag》

《Docker镜像进阶:了解其背后的技术原理》

《教你如何修改运行中的容器端口映射》

《k8s学习笔记:介绍&上手》

《k8s学习笔记:缩扩容&更新》

《Docker君带你认识Docker Swarm》

《Docker 基础用法和命令帮助》

《在K8S上搭建Redis集群》

《灰度部署、滚动部署、蓝绿部署》

《PM2实践指南》

《Docker垃圾清理》

《Kubernetes(k8s)底层网络原理刨析》

《容器环境下Node.js的内存管理》

《MySQL 快速创建千万级测试数据》

《Linux 与 Unix 到底有什么不同?》

《浅谈几种常见 RAID 的异同》

《如何超越你身边的大多数人》

《Git 笔记-程序员都要掌握的 Git》

《老司机必须懂的MySQL规范》

《2019版最新Linux 技能图谱,你值得拥有!》



免责声明:本文内容来源于网络,所载内容仅供参考。转载仅为学习和交流之目的,如无意中侵犯您的合法权益,请及时联系西岐Docker君!




Docker中Image、Container与Volume的迁移 第3张 Docker中Image、Container与Volume的迁移 第4张 Docker中Image、Container与Volume的迁移 第5张 dockerchina Docker中Image、Container与Volume的迁移 第6张


赞(2)
未经允许不得转载:工具盒子 » Docker中Image、Container与Volume的迁移