chenqz 2017-08-29 8033浏览量
随着17.05版本的发布,Docker对于镜像构建这块也作了一项重要更新,那就是 multi-stage build(多阶段构建),这对于长期因为构建镜像太大而困扰的小伙伴们来说真是雪中送炭。
在17.05版本之前,我们构建Docker镜像时,通常会采用两种方式:
将所有的构建过程编写在同一个Dockerfile中,包括项目及其依赖库的编译、测试、打包等流程,这里可能会带来的一些问题:
这里以一个简单的JAVA项目镜像构建为例来说明这两种构建方式,该项目仅仅包含一个App.java类:
public class App {
public static void main(String[] args) {
System.out.println("Hello, multi-stage build...");
}
}
FROM dojomadness/alpine-jdk8-maven:latest
# add pom.xml and source code
ADD ./pom.xml pom.xml
ADD ./src src/
# package jar and remove source code and temporary class files
RUN mvn clean package && cp -f target/msb-1.0.jar msb.jar && rm -rf pom.xml src/ target/
# run jar
CMD ["java", "-jar", "msb.jar"]
这里是将所有的构建流程都编写在同一个Dockerfile中,但为了尽可能地减小镜像层次,我们将多个执行命令合并到同一个RUN指令中,同时我们需要自行清理掉源码目录文件以及编译后的临时目录文件,以防止源码泄露。
这里我们需要分为两个阶段:
1)编译打包 Dockerfile.2.1
FROM maven:3.5.0-jdk-8-alpine
# add pom.xml and source code
ADD ./pom.xml pom.xml
ADD ./src src/
# package jar
RUN mvn clean package
2)构建镜像 Dockerfile.2.2
From openjdk:8-jre-alpine
# copy jar
COPY ./msb.jar msb.jar
# run jar
CMD ["java", "-jar", "msb.jar"]
3)整合两个构建阶段 build.sh
#!/bin/bash
# First stage: complete build environment
docker build -t msb:build -f Dockerfile.2.1 .
# create temporary container
docker create --name extract msb:build
# extract jar
docker cp extract:/target/msb-1.0.jar ./msb.jar
# remove temporary container
docker rm -f extract
# Second stage: minimal runtime environment
docker build --no-cache -t msb:build-2 -f Dockerfile.2.2 .
# remove local jar
rm -rf ./msb.jar
这里我们编写了两个Dockerfile和一个Shell脚本,通过两阶段将最终镜像构建出来,但可预见的一个问题是,假若有多个项目彼此关联和依赖,就需要我们维护多个Dockerfile,或者需要编写更复杂的build.sh脚本,导致后期维护成本很高。
在Docker 17.05 多阶段构建推出之后,我们就可以很容易规避前面遇到的这些问题,并且只需要维护一个Dockerfile即可:
# 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/msb-1.0.jar msb.jar
# run jar
CMD ["java", "-jar", "msb.jar"]
对于上面的Dockerfile是不是很熟悉,它仅仅是将第二种方式中的两个Dockerfile合并到同一个Dockerfile中,同时在构建过程中自动帮您完成了build.sh的流程。
对于multi-stage build,其关键点主要有两点:
FROM image[:tag | @digest] AS stage
--from
参数,指明引用前面哪一个构建阶段的成果,格式如下:COPY --from=stage ...
同理,多阶段构建同样可以很方便地将多个彼此依赖的项目通过一个Dockerfile就可轻松构建出期望的容器镜像,而不用担心镜像太大、源码泄露等风险。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
云端最佳容器应用运行环境,安全、稳定、极致弹性