使用Docker多阶段构建来减小镜像大小的方法

2020-06-17 06:11:02易采站长站整理

本文讲述了如何通过 Docker 的多阶段构建功能来大幅度减小镜像大小,适用于需要在 Dockerfile 中构建程式(如 javac),且需要另外安装编译工具链的镜像。(如 Java)

先来学习单词(本文全部采用中文词汇,如需查询外文文档可对照该词汇表。理论上个人不赞成翻译术语):

multi-stage 多阶段
build 构建
image 镜像
stage 阶段

再来看一下效果: 原 110M+,现 92M。

对比一下 Dockerfile

优化前 Dockerfile:


FROM openjdk:8u171-jdk-alpine3.8

ADD . /app
WORKDIR /app

RUN apk add maven
&& mvn clean package
&& apk del maven
&& mv target/final.jar /
&& cd /
&& rm -rf /app
&& rm -rf /root/.m2

ENTRYPOINT java -jar /final.jar

优化后 Dockerfile:


FROM openjdk:8u171-jdk-alpine3.8 as builder

ADD . /app
WORKDIR /app

RUN apk add maven
&& mvn clean package
&& apk del maven
&& mv target/final.jar /

FROM openjdk:8u181-jre-alpine3.8 as environment
WORKDIR /
COPY --from=builder /final.jar .
ENTRYPOINT java -jar /final.jar

很明显,优化后的 Dockerfile 新增了 FROM AS 这个命令,并出现了两个 FROM。这就是多阶段构建。

了解一下多阶段构建

多阶段构建是 Docker 17.05 的新增功能,它可以在一个 Dockerfile 中使用多个 FROM 语句,以创建多个 Stages(阶段)。每个阶段间独立(来源请求),可以通过 COPY –from 来获取其它阶段的文件。我们来打个比方,把最终镜像比作一盘菜(炒青椒)。把原料青椒炒完后上桌。


# 对比清单
镜像 -> 一盘菜
第一个阶段 -> 炒
第二个阶段 -> 上桌

两个阶段的目标是做好(生成)最终的菜(镜像)。我们要做的是将第一个阶段「炒」出来的食物进行「上桌」。我们的目标是 做出菜,且 菜盘子(盛菜和中间产物)最轻。

可视化流程如下:


# 做菜流程
... 省略原料
原料 -> [第一个阶段——炒] # 此时盘子里有炒的工具、炒的结果和中间产物
# 这时候开启第二个阶段,只保留炒的结果,而不再需要其它。
-> 炒的结果 -> [开始上桌,只保留结果] # 把炒出来的青椒拿来(COPY --from),其它不要
-> 最终是一盘菜。

现在应该大致理解多阶段构建的流程了吧。我们把话筒交给 Java,看看在 Dockerfile 中使用编译工具构建一个 JAR,并只保留构建完的 JAR 和运行时交给 Image,其它则扔掉应该怎么做: