Docker多步构建更小的Java镜像

本文讲的是Docker多步构建更小的Java镜像【编者的话】最新版Docker将支持多步构建(Multi-stage build),这样使用单个Dockerfile就可以定义多个中间镜像用于构建,测试以及发布等多个步骤,并且有效减小最终镜像的大小。

【深圳站|3天烧脑式Kubernetes训练营】培训内容包括:Kubernetes概述、架构、日志和监控,部署、自动驾驶、服务发现、网络方案等核心机制分析,进阶篇——Kubernetes调度工作原理、资源管理及源码分析等。

Github仓库: arun-gupta/docker-java-multistage

DockerCon 2017中与Java开发者直接相关的内容有:

Docker多步构建(Docker Multi-stage build)
Oracle JRE in Docker Store
这篇博客介绍了为什么需要Docker多步构建(Docker Multi-stage build),并且通过一个示例展示了如何构建更小的Java镜像。

为什么需要多步构建?

为Java应用构建Docker镜像意味着编译源代码以及打包目标代码。开发者通常会使用Maven或者Gradle来构建JAR或WAR文件。若使用Maven镜像作为基础镜像来构建Java应用,则需要下载所有Maven依赖。下载的JAR包数目由pm.xml决定,有可能会非常多。这样的话,生成的Docker镜像中将留下太多多余的文件。

下面为示例Dockerfile:

FROM maven:3.5-jdk-8

COPY src /usr/src/myapp/src
COPY pom.xml /usr/src/myapp
RUN mvn -f /usr/src/myapp/pom.xml clean package

ENV WILDFLY_VERSION 10.1.0.Final
ENV WILDFLY_HOME /usr

RUN cd $WILDFLY_HOME && curl http://download.jboss.org/wildfly/$WILDFLY_VERSION/wildfly-$WILDFLY_VERSION.tar.gz | tar zx && mv $WILDFLY_HOME/wildfly-$WILDFLY_VERSION $WILDFLY_HOME/wildfly

RUN cp /usr/src/myapp/target/people-1.0-SNAPSHOT.war $WILDFLY_HOME/wildfly/standalone/deployments/people.war

EXPOSE 8080

CMD ["/usr/wildfly/bin/standalone.sh", "-b", "0.0.0.0"] 

由Dockerfile可知:

maven:3.5-jdk-8 是基础镜像
将源代码拷贝到镜像中
Maven用于构建应用
下载并安装WildFly
将生成的.war文件拷贝到WildFly的deployments目录
启动WildFly
这个Dockefile存在这些问题:

使用Maven作为基础镜像的话,还需要安装和配置WildFly。
构建应用时需要下载很多Maven依赖,它们会继续留在镜像中,但是运行应用时并不需要它们。这导致了镜像过大。
修改WildFly版本则需要修改Dockerfile,并重新构建镜像。如果直接使用WildFly镜像作为基础镜像,情况会简单很多。
打包应用之前,需要进行单元测试,那么,测试的依赖也需要留在生成的镜像中,这其实是没必要的。
当然,也可以采用其他方式构建Docker镜像。比如,可以将Dockerfile拆分为两个。第一个Dockerfile以Maven镜像为基础镜像,用于构建应用,并将构建好的.war文件通过数据卷(volume)复制到共享的目录;第二个Dockerfile以WildFly镜像作为基础镜像,从数据卷将.war文件拷贝出来就好了。这个方法也是有问题的,因为需要维护多个Dockerfile,并且通过数据卷拷贝文件也不方便。

什么是Docker多步构建?

多步构建(multi-stage build)允许在Dockerfile中使用多个FROM指令。两个FROM指令之间的所有指令会生产一个中间镜像,最后一个FROM指令之后的指令将生成最终镜像。中间镜像中的文件可以通过COPY --from=<image-number>指令拷贝,其中image-number为镜像编号,0为第一个基础镜像。没有被拷贝的文件都不会存在于最终生成的镜像,这样可以减小镜像大小。

FROM指令可以使用as <stage-name>来指定步骤名称(stage name):

FROM maven:3.5-jdk-8 as BUILD
这样的话,COPY指令的--from选项可以使用步骤名称代替镜像编号。

下面为示例Dockerfile:

FROM maven:3.5-jdk-8 as BUILD

COPY src /usr/src/myapp/src
COPY pom.xml /usr/src/myapp
RUN mvn -f /usr/src/myapp/pom.xml clean package

FROM jboss/wildfly:10.1.0.Final

COPY --from=BUILD /usr/src/myapp/target/people-1.0-SNAPSHOT.war /opt/jboss/wildfly/standalone/deployments/people.war

由Dockerfile可知:

一共有两个FROM指令,因此为两步构建。
maven:3.5-jdk-8 是第一步构建的基础镜像。这一步用于构建应用的WAR文件。这一步的名称为build。
jboss/wildfly:10.1.0.Final 是第二步构建的基础镜像。第一步构建的WAR文件通过COPY --from指令拷贝到WildFly的deloyments目录。
Docker多步构建有什么好处?

仅需要一个Dockerfile来定义整个构建过程。这样,不需要定义多个Dockerfile,也不需要使用数据卷来拷贝文件。
可以为最终镜像选择合适的基础镜像,来满足生产环境的需求,这样可以有效减小最终镜像的大小。另外,构建步骤的多余文件都被丢弃了。
使用官方的WildFly镜像作为生产镜像的基础镜像,而不是手动安装和配置WildFly。这样,WildFly升级时将非常方便。
注:Docker多步构建正在开发中,还没有正式发布。可以通过 curl -fsSL https://test.docker.com/ | sh命令安装最新的测试版Docker试用多步构建。

使用第一个Dockerfile构建的镜像为816MB,而使用多步构建的话,镜像只有584MB。

docker-java-multistage $ docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE
people                              multistage          d36a4b82ad87        59 seconds ago      584MB
people                              singlestage         13dbcf8f54f6        5 minutes ago       816MB

可知,使用多步构建可以有效减小镜像大小。

查看PR #31257,有更加详细的讨论。

欢迎加入我们Fundebug的Docker技术交流群: 305097057。

原文: Creating Smaller Java Image using Docker Multi-stage Build

译者: Fundebug

版权声明:
转载时请注明作者Fundebug以及本文地址:

https://blog.fundebug.com/2017 ... sock/

原文发布时间为:2017-05-02

本文作者:Fundebug

本文来自合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。

原文标题:Docker多步构建更小的Java镜像

时间: 2025-01-26 14:58:55

Docker多步构建更小的Java镜像的相关文章

Java微服务开发指南 -- 使用Docker和Kubernetes构建可伸缩的微服务

使用Docker和Kubernetes构建可伸缩的微服务     从现在开始,我们将从更高的维度讨论微服务,涵盖了组织敏捷性.设计和依赖的思考.领域驱动设计以及Promise理论.当我们深入使用之前介绍的三个流行的微服务框架:Spring Boot.Dropwizard和WildFly Swarm,我们能够使用它们开箱即用的能力去构建一个暴露或者消费REST服务的应用,能够使用外部环境对应用进行配置,可以打包成一个可执行的jar,同时提供Metrics信息,但这些都是围绕着一个微服务实例.当我们

5个构建第一个Java镜像的小窍门

本文讲的是5个构建第一个Java镜像的小窍门[编者的话]Arun Gupta是<Docker for Java Developers>一书的作者,本文介绍了构建Java镜像的五个小窍门,从而以超越基本概念和框架的方式开启Docker容器之旅. 如果你是一个热切期待在你的组织内部迁移到容器技术的企业级软件开发人员,那么你会有更多的兴趣来学习Docker背后的基础概念以及围绕Docker的常用的编排框架.在本文中,我将就这些基本概念进行扩展并提供一些简单而使用的小窍门来构建你的第一个使用Java编

微容器:更小的,更轻便的Docker容器

本文讲的是微容器:更小的,更轻便的Docker容器,[编者的话]本文介绍了微容器的概念和好处,并用一些例子介绍了如何构建微镜像,从scratch到Alpine Linux,并推荐了一些已有的基础微镜像,方便为几乎所有主流语言的应用构建微镜像.本文也指出了构建微镜像的基本原理:将构建时依赖和运行时依赖分开,构建时所用的镜像包含所有构建所用的工具,它可以比较大,但运行时的基础镜像应该仅包含运行时依赖.使用微容器,no going back! Docker 使你能把你的应用和应用的依赖打包到一个良好的

Docker容器:更小不一定更好

本文讲的是Docker容器:更小不一定更好,[编者的话]按正常逻辑来说,我们应该选择体积较小的Docker容器.然而事实是,体积小却并不一定能带来性能上的优势.本文将介绍一个使用了一个体积稍大一点的容器,从而将性能提高30倍以上的例子. 按道理来说,我们应该选择体积较小的Docker容器.然而事实是,体积小却并不一定能带来性能上的优势.本文将介绍一个使用了一个体积稍大一点的容器,从而将性能提高30倍以上的例子. 摘要 当使用grep来处理大量的数据的时候,busybox中带的grep速度慢的让人

[译] 如何在无损的情况下让图片变的更小

本文讲的是[译] 如何在无损的情况下让图片变的更小, 原文地址:Making Photos Smaller Without Quality Loss 原文作者:Stephen Arthur 译文出自:掘金翻译计划 译者:Xat_MassacrE 校对者:meifans,windmxf 如何在无损的情况下让图片变的更小 Yelp(美国最大点评网站)已经有超过 1 亿张用户上传的照片了,其中不但有晚餐.理发等活动的照片还有我们的新特性照片 -- #yelfies(一种在拍摄时,加上自拍头像的一种新的

构建可扩展的Java EE应用(一)

对于一个具备使用价值的应用而言,其使用者有可能会在一段时间内疯狂的增 长.随着越来越多的关键性质的应用在Java EE上运行,很多的Java开发者也开始 关注可扩展性的问题了.但目前来说,大部分的web 2.0站点是基于script语言编 写的,对于Java应用可扩展能力,很多人都抱着质疑的态度.在这篇文章中, Wang Yu基于他本身在实验室项目的经验来展示如何构建可扩展的java应用,同时 ,基于一些在可扩展性上做的比较失败的项目给读者带来构建可扩展java应用的 实践.理论.算法.框架和经

把扫描版pdf变得更小更清晰的技巧

  如何让扫描版pdf变得更小更清晰 1.首先用acrobat导出图片.点击菜单栏上的"另存为"->"图像"->"png"保存成png格式.在弹出的文件选择框右边有个设置按钮,点开进行设置.一般扫描后的黑白图像是灰度图,我们这里保存成灰度.(如果是黑白位图形式的,文件一般很小,不需要处理.) 2.用photoshop打开需要所得到的图片.看一下尺寸,如果宽度小于1400则需要放大,点击"图像"->"

微服务的持续集成,四步“构建”一个代码世界

本文讲的是微服务的持续集成,四步"构建"一个代码世界,大师Martin Fowler对持续集成是这样定义的:持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成.每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误. 今天我们就来聊一聊微服务的持续集成. 目录 一.持续集成之构建 二.持续集成之部署 三.持续集成之测试 四.持续集成之发布 五.总结 一.持续集成之构建 当微服务产生

马云相信,应该拆得更小一点

阿里巴巴之前的拆分所取得的成绩,使得马云相信,应该拆得更小一点. 把变化作为企业文化的阿里巴巴[微博]的员工需要再一次"拥抱变化"了.而且,这一次变化很大. 1月10日,阿里巴巴集团董事局主席兼CEO马云[微博]宣布将整个阿里巴巴集团分为25个事业部.25个事业部的日常业务发展,将由这25个事业部的总裁(总经理)直接决策管理.在集团层面,阿里将设立战略决策委员会和战略管理执行委员会,前者由董事局负责,后者多由原阿里巴巴旗下子公司和事业群的总裁们构成. 1月15日,另一则重大信息公布,这