选择合适的基础镜像
Debian/Ubuntu
CentOS/Fedora
busybox
alpine
动态链接库/静态链接库
处理构建工具-多阶段构建
要想大幅度减少镜像的体积,多阶段构建是必不可少的。多阶段构建的想法很简单:“我不想在最终的镜像中包含一堆 C 或 Go 编译器和整个编译工具链,我只要一个编译好的可执行文件!”
多阶段构建可以由多个 FROM 指令识别,每一个 FROM 语句表示一个新的构建阶段,阶段名称可以用 AS 参数指定,例如:
FROM gcc AS mybuildstage
COPY hello.c .
RUN gcc -o hello hello.c
FROM ubuntu
COPY --from=mybuildstage hello .
CMD ["./hello"]
注意:COPY --from=imageName
, 在复制文件时,源和目标如果是相对的目录或文件,则都是相对于各自的WORKDIR。
本例使用基础镜像 gcc 来编译程序 hello.c,然后启动一个新的构建阶段,它以 ubuntu 作为基础镜像,将可执行文件 hello 从上一阶段拷贝到最终的镜像中。最终的镜像大小是 64 MB,比之前的 1.1 GB 减少了 95%:
???? → docker images minimage
REPOSITORY TAG ... SIZE
minimage hello-c.gcc ... 1.14GB
minimage hello-c.gcc.ubuntu ... 64.2MB
还能不能继续优化?当然能。在继续优化之前,先提醒一下:
在声明构建阶段时,可以不必使用关键词 AS,最终阶段拷贝文件时可以直接使用序号表示之前的构建阶段(从零开始)。也就是说,下面两行是等效的:
COPY --from=mybuildstage hello .
COPY --from=0 hello .
如果 Dockerfile 内容不是很复杂,构建阶段也不是很多,可以直接使用序号表示构建阶段。一旦 Dockerfile 变复杂了,构建阶段增多了,最好还是通过关键词 AS 为每个阶段命名,这样也便于后期维护。
处理依赖-分层构建
可以通过 docker 镜像分层的原理,将安装依赖的过程放在一层里,然后代码放在最后 COPY 进去,因为一般情况下,都是代码频繁的变动,依赖的软件不会经常变动,这样可以利用 build 时的 cache,加速 build 的过程。