问题

之前一直有这个问题困扰我,不知道大家有没有遇到过,当我们在容器中部署某个软件时如果软件的压缩包比较大那我们可能需要把压缩包删除后再去做镜像,此时你会发现镜像还是两个压缩包左右的大小,甚至删除后镜像可能会更大,这个问题就很容易导致镜像越来越大无法维护,最近找到了一个解决方法,在这里分享一下


分析

这个跟docker的原理有关系,因为镜像是按照层存储,这样做最大好处很直观,版本更新时只需要下载软件的下一层相当于是软件的增量包大概是这个意思,而如果你不分层就需要下载软件的全量包这样的话十分麻烦。用户既可以使用 docker load 来导入镜像存储文件到本地镜像库,也可以使用 docker import 来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。


解决

知道了原因的话那解决也会相对简单一些,既然docker load会保存文件的历史记录和原数据,那我们使用docker import导入容器的快照就可以了。大概就是恢复到打包容器时候的样子,是一个快照,没有历史记录。这个是参考:导出和导入

导出容器

  • 如果要导出本地某个容器,可以使用 docker export 命令,格式如下
docker export ContainerId > containerPackage.tar

ContainerId 代表容器id,containerPackage.tar压缩包名称这个无所谓

查看容器id

docker基于镜像打包 docker镜像打包时变小_运维


导出容器快照为tar文件

docker基于镜像打包 docker镜像打包时变小_容器_02


这样将导出容器快照到本地文件,等待完成,查看文件

docker基于镜像打包 docker镜像打包时变小_docker_03

导入容器快照

使用 docker import 从容器快照文件中再导入为镜像,格式如下

cat edas.tar  | docker import - luntek/centos_edatest:1.0

edas.tar为容器快照,luntek应该是仓库名称,centos_edatest是项目名称

docker基于镜像打包 docker镜像打包时变小_容器_04

上传镜像

docker push luntek/images_name:tag

如果docker镜像太大上传的过程中可能会报错Retrying in 10 second
解决:编辑/etc/selinux/config文件,关闭SELINUX,将值设置为disabled

vi /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted