本文是本人项目踩坑经验,如有错漏请见谅!
背景需求:
一个已经配置好的容器(无build文件)需要部署到生产环境中,容器内有程序绑定了宿主环境的硬件信息。需求部署后能让第三方很难追溯回滚至镜像加密程序前的状态和加密程序本身以至于跳过保护措施。(镜像和宿主都是linux系统)
方案:
Docker除了build文件外,有2种导入导出命令组合。命令使用可参考Docker文档。这2种组合为:对镜像的save/load 和 对容器的export/import。其中export/import能很好的满足需求,export会导出容器在导出时的文件系统,相当于抹去了镜像的历史改动(layers)。
网上有很多export/import的例子,都是把原始的几乎无改动的容器如debian:latest导入导出,看上去很容易也都工作正常。实际拿自己项目的容器操作后发现很复杂,坑很多,前后费了我一周的时间才完全搞定。见坑如下:
坑1,export/import后的image没有任何配置参数,当然也无启动参数,大概率下按原来的启动凡是启动镜像必会出错。查询文档后,发现在import时可以设定CMD作为启动参数。(docker import)按Dockers的文档,在导入时可设定的参数很有限,实践后发现,导入时启动参数设定只能仅让新的image可以启动运行,并不意味着容器的功能都如导入前一样。如何让导入后的image能和导入前拥有相同的参数配置,见下文image配置修改。
坑2,这个是各大坑,本项目的镜像是一个运行在x64系统内的x86镜像。却在import后被系统自动设为amd64的架构。启动时,会遇到Unable to find image 'XXX' locally. 在最新的Docker官方文档里import新支持了--platform参数,但在本项目的系统版本内无官方解。解法见下文image配置修改。
坑3, 由于export会导出容器在导出时的文件系统,导出的数据包中也包含了容器系统运行时的文件。这些运行时文件可能会对导入后启动产生未知影响。本例中,/tmp/目录下有个某程序生成的lock文件,该lock文件的存在造成导入后再启动镜像时,程序认为已经启动而跳过启动。分析了很久才发现是/tmp/目录下的lock文件在随机次启动时会阻止相应程序启动。在清空导出包内的/tmp目录后重新导入,问题解决。该坑只能具体问题具体分析,建议在使用export/import时,在导入前应该过一遍导出数据包,清理一些linux典型的临时数据目录。
image配置修改方法(野路子办法)
- docker images 查看新导入的image ID备用
- 关闭docker service, systemctl stop docker.service
- cd /var/lib/docker/image/btrfs/imaged, 下列步骤中相对路径以此为基准
- 在content/sha256中找到对应的image ID的文件,文件为json格式,打开编辑,建议只作必要的修改,比如image的启动命令,平台架构,环境变量,完成后保存退出 (参考比较导出前的image的对应文件内容)
- 重新计算修改后ID配置文件的sha256 HASH, 运行命令sha256sum <image ID>
- 把ID配置文件用新的sha256 HASH重命名 mv <old HASH> <new HASH>
- 修改/var/lib/docker/image/btrfs/repository.json中的旧HASH为新HASH值
- 运行命令 stat -c ‘%y’ content/sha256/<new HASH> 获取新配置文件的修改时间戳
- 时间戳格式调整为 2023-03-27T20:48:02.401189138+08:00
- 重命名metadata/sha256/<old HASH>为metadata/sha256/<new HASH>
- 运行echo ‘2023-03-27T20:48:02.401189138+08:00’ | xargs echo -n > ./metadata/sha256/<new HASH>/lastUpdated
- 重新启动docker服务 systemctl start docker.service
- 可能启动后镜像名和版本会丢失,使用docker tag重新设定
希望对踩了类似坑的人有帮助~~
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)