作者: 张首富
时间: 2019-05-03
个人博客: www.zhangshoufu.com
QQ群: 895291458

前提

因为公司业务需求,需要到客户现场部署我们代码的离线环境,因为各大银行和运营商所提供的底层系统各不相同,代码不一定能运行的起来,所以我们就采用了docker版的离线部署方式,报我们所有的应用全打成docker包,然后再到客户现场部署. 但是这又引发了另外一个问题,因为我们的客户一般都是银行和运营商,所以我们要拷贝个东西到他们的系统里面是很费劲的,因为全是docker包,因为我们打包没有精简,导致打出来的docker非常庞大,传输文件到客户服务器里面往往需要大半天时间或者更久. 为了提高工作效率,缩短传输包的时间,我们决定对docker镜像进行精简

精简docker镜像的必要性

1,我们大家都知道docker镜像是分层存储的,镜像层依赖于一系列底层技术(FileSystem,copy-on-wirte,union mounts联合挂载),而docker镜像最多有127层,当超过127层的时候docker镜像打包就会失败. 2,精简docker镜像大小能减少我们的构建时间,只装必须使用的包,不需要的就不装 3,减少磁盘使用量 4,因为包含的文件少,所以漏洞如果就少 5,传输速度,部署速度加快

精简docker镜像的建议

a, 选择基础镜像

当我们编写Dockerfile FROM的时候选择最合适的最小的基础镜像,我们在这个基础上安装我们必须的安装包. 常用的 Linux 系统镜像一般有 Ubuntu、CentOs、Alpine,其中 Alpine 更推荐使用。大小对比如下:


Alpine 是一个高度精简又包含了基本工具的轻量级 Linux 发行版,基础镜像只有 4.41M,各开发语言和框架都有基于 Alpine 制作的基础镜像,强烈推荐使用它。

查看上面的镜像尺寸对比结果,你会发现最小的镜像也有 4.41M,那么有办法构建更小的镜像吗?答案是肯定的,例如 gcr.io/google_containers/pause-amd64:3.1 镜像仅有 742KB。为什么这个镜像能这么小?在为大家解密之前,再推荐两个基础镜像:

1) scratch 镜像

scratch 是一个空镜像,只能用于构建其他镜像,比如你要运行一个包含所有依赖的二进制文件,如centos 7.5镜像,他就是基于scratch来构建的,他的Dockerfile文件来构建的

FROM scratch
ADD centos-7-docker.tar.xz /

LABEL org.label-schema.schema-version = "1.0" \\\\
    org.label-schema.name="CentOS Base Image" \\\\
    org.label-schema.vendor="CentOS" \\\\
    org.label-schema.license="GPLv2" \\\\
    org.label-schema.build-date="20180531"

CMD ["/bin/bash"]

centos镜像使用了scratch 作为基础镜像,这个镜像本身是不占空间的,使用它构建的镜像大小几乎和二进制文件本身一样大,所以镜像非常小。

2) busybox 镜像

scratch 是个空镜像,如果希望镜像里可以包含一些常用的 Linux 工具,busybox 镜像是个不错选择,镜像本身只有 1.16M,非常便于构建小镜像。

b, 串联 DOckerfile 指令

大家在定义 Dockerfile 时,如果太多的使用 RUN 指令,经常会导致镜像有特别多的层,镜像很臃肿,而且甚至会碰到超出最大层数(127层)限制的问题,遵循 Dockerfile 最佳实践,我们应该把多个命令串联合并为一个 RUN(通过运算符&&和/ 来实现),每一个 RUN 要精心设计,确保安装构建最后进行清理,这样才可以降低镜像体积,以及最大化的利用构建缓存。 下面是一个优化前 Dockerfile: 下面的例子只是做个测试,正常来讲没有人会这样构建docker镜像 docker镜像打包比对

FROM centos:7.5.1804
COPY ./*.repo /etc/yum.repos.d/
RUN yum -y install nginx
RUN yum -y install mariadb*
CMD nginx