Dockerfile作为基础框架即代码的重要载体,随着容器化的不断推进,起到的作用愈加强大,Docker镜像在构建过程中,关于层数与大小的控制方面如何进行控制,在这篇文章中结合具体示例进行整理和总结。
基本原则1: 在保证需求和扩展性的前提下,尽可能删除不用的组件,或者选择合理尺寸的镜像。
说明1:基础镜像并非越小越好,满足需求和扩展性以及开发者使用的熟悉程度才是更重要的因素。
如果只是基础镜像越小越好的话,所有从from scratch生成的以busybox等小型系统为基础的镜像将会成为统一的选择。Alpine将镜像的大小控制在5M左右,但是也并非是所有的镜像都在统一使用Alpine镜像,使用centos和ubuntu的镜像仍然很多。Alpine镜像的重要基础之一的musl libc本身也给使用带来了限制性。
说明2: 镜像功能的组合和对镜像大小的需求之间的平衡
容器功能尽可能单一化与简单化,原本跑在虚拟机或者物理机上,现在几乎不做任何改变在容器中启动起来的容器化方式对系统改造影响确实会少一些,但是问题也会出现,比如可能会出现希望在一个容器中同时启动多个进程,这样的功能需求对镜像的大小和构建的复杂度都造成直接的影响,表面的现象可能是Docker的功能是否支持这样的特性需求,较深层次的问题往往是传统方式的架构在向着容器化和微服务演变的过程中的方式是否考虑到当下容器相关技术的特点和支撑能力。
基本原则2: 尽可能减少镜像的层数
我们知道镜像是分层的,如下图的示例所示,使用镜像所启动的容器之中,每一次的操作都会形成一个新的可写的层。
而在Dockerfile中,每一行的命令都会生成一个新层,比如我们以Alpine镜像作为基础镜像,在其中将时区设定从缺省的UTC改成CST,则需要如下三步即可
- 步骤1: apk add tzdata
- 步骤2: cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
- 步骤3: echo “Asia/Shanghai” > /etc/timezone
确认Alpine基础镜像的分层,可以看到有2层
[root@host132 ~]# docker run --rm -it alpine cat /etc/alpine-release
3.10.2
[root@host132 ~]# docker history alpine
IMAGE CREATED CREATED BY SIZE COMMENT
961769676411 3 weeks ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:fe64057fbb83dccb9… 5.58MB
[root@host132 ~]#
在这个基础之上,如果使用如下Dockerfile
[root@host132 dockerfile]# cat Dockerfile
FROM alpine:3.10.2
RUN apk add tzdata
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo "Asia/Shanghai" > /etc/timezone
[root@host132 dockerfile]#
使用docker build进行构建,生成名为alpinemorelayers的镜像,