多阶段构建指在Dockerfile中使用多个FROM语句,每个FROM指令都可以使用不同的基础镜像,并且是一个独立的子构建阶段。使用多阶段构建打包Java应用具有构建安全、构建速度快、镜像文件体积小等优点,本文以Github上的Java Maven项目为例,结合阿里云容器镜像服务(ACR)的镜像构建服务,介绍如何进行多阶段构建。
前提条件
背景信息
镜像构建的通用问题
- Dockerfile编写有门槛
开发者(尤其是Java)习惯了语言框架的编译便利性,不知道如何使用Dockerfile构建应用镜像。
- 镜像容易臃肿
构建镜像时,开发者会将项目的编译、测试、打包构建流程编写在一个Dockerfile中。每条Dockerfile指令都会为镜像添加一个新的图层,从而导致镜像层次深,镜像文件体积特别大。
- 存在源码泄露风险
打包镜像时,源代码容易被打包到镜像中,从而产生源代码泄漏的风险。
多阶段构建优势
- 保证构建镜像的安全性
当您使用Dockerfile多阶段构建镜像时,需要在第一阶段选择合适的编译时基础镜像,进行代码拷贝、项目依赖下载、编译、测试、打包流程。在第二阶段选择合适的运行时基础镜像,拷贝基础阶段生成的运行时依赖文件。最终构建的镜像将不包含任何源代码信息。
- 优化镜像的层数和体积
构建的镜像仅包含基础镜像和编译制品,镜像层数少,镜像文件体积小。
- 提升构建速度
使用构建工具(Docker、Buildkit等),可以并发执行多个构建流程,缩短构建耗时。
步骤一:使用多阶段构建Dockerfile
- 第一阶段:选择Maven基础镜像(Gradle类型也可以选择相应Gradle基础镜像)完成项目编译,拷贝源代码到基础镜像并运行RUN命令,从而构建Jar包。
- 第二阶段:拷贝第一阶段生成的Jar包到OpenJDK镜像中,设置CMD运行命令。
# First stage: complete build environment
FROM maven:3.5.0-jdk-8-alpine AS builder
# add pom.xml and source code
ADD ./pom.xml pom.xml
ADD ./src src/
# package jar
RUN mvn clean package
# Second stage: minimal runtime environment
From openjdk:8-jre-alpine
# copy jar from the first stage
COPY --from=builder target/my-app-1.0-SNAPSHOT.jar my-app-1.0-SNAPSHOT.jar
EXPOSE 8080
CMD ["java", "-jar", "my-app-1.0-SNAPSHOT.jar"]
步骤二:绑定源代码仓库
在容器镜像服务控制台,绑定您托管的代码仓库,以下内容以GitHub为例。
步骤三:新建镜像仓库
步骤四:执行构建
执行结果
- 查看构建的镜像
在个人版实例管理页面左侧导航栏中选择操作列的管理,进入仓库详情页面。单击镜像版本,查看构建的镜像。
,单击仓库名称或目标仓库 - 查看镜像层数
使用Docker客户端登录镜像仓库,执行以下命令,拉取构建的镜像并检查镜像层数。可以发现仅包含了第一阶段编译Jar包,大小增加有限,镜像层数控制在四层。
docker pull registry.cn-hangzhou.aliyuncs.com/docker-builder/java-multi-stage:master docker inspect registry.cn-hangzhou.aliyuncs.com/docker-builder/java-multi-stage:master | jq -s .[0][0].RootFS { "Type": "layers", "Layers": [ "sha256:f1b5933fe4b5f49bbe8258745cf396afe07e625bdab3168e364daf7c956b6b81", "sha256:9b9b7f3d56a01e3d9076874990c62e7a516cc4032f784f421574d06b18ef9aa4", "sha256:edd61588d12669e2d71a0de2aab96add3304bf565730e1e6144ec3c3fac339e4", "sha256:2be89a7ccd49878fb5f09d6dfa5811ce09fc1972f0a987bbb5a006992aa3dff3" ] }
- 运行镜像,查看运行结果
使用Docker客户端登录镜像仓库,执行以下命令,运行镜像,查看运行结果。
docker run -ti registry.cn-hangzhou.aliyuncs.com/docker-builder/java-multi-stage:master Hello World!