Docker多步构建更小的Java镜像

简介: 译者按: 最新版Docker将支持多步构建(Multi-stage build),这样使用单个Dockerfile就可以定义多个中间镜像用于构建,测试以及发布等多个步骤,并且有效减小最终镜像的大小。

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

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

译者: Fundebug

为了保证可读性,本文采用意译而非直译。

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

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

这篇博客介绍了为什么需要****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****。

img_441138c7e03a0081638eee3852d91b5a.jpe
nodejs-qq-group.jpeg

版权声明:转载时请注明作者 Fundebug以及本文地址: https://blog.fundebug.com/2017/05/02/about-docker-sock/

目录
相关文章
|
8天前
|
缓存 监控 持续交付
|
5天前
|
Kubernetes 负载均衡 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
本文介绍了Docker和Kubernetes在构建高效微服务架构中的应用,涵盖基本概念、在微服务架构中的作用及其实现方法。通过具体实例,如用户服务、商品服务和订单服务,展示了如何利用Docker和Kubernetes实现服务的打包、部署、扩展及管理,确保微服务架构的稳定性和可靠性。
33 7
|
4天前
|
Kubernetes 负载均衡 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
【10月更文挑战第22天】随着云计算和容器技术的快速发展,微服务架构逐渐成为现代企业级应用的首选架构。微服务架构将一个大型应用程序拆分为多个小型、独立的服务,每个服务负责完成一个特定的功能。这种架构具有灵活性、可扩展性和易于维护的特点。在构建微服务架构时,Docker和Kubernetes是两个不可或缺的工具,它们可以完美搭档,为微服务架构提供高效的支持。本文将从三个方面探讨Docker和Kubernetes在构建高效微服务架构中的应用:一是Docker和Kubernetes的基本概念;二是它们在微服务架构中的作用;三是通过实例讲解如何使用Docker和Kubernetes构建微服务架构。
25 6
|
3天前
|
负载均衡 应用服务中间件 nginx
基于Nginx和Consul构建自动发现的Docker服务架构——非常之详细
通过使用Nginx和Consul构建自动发现的Docker服务架构,可以显著提高服务的可用性、扩展性和管理效率。Consul实现了服务的自动注册与发现,而Nginx则通过动态配置实现了高效的反向代理与负载均衡。这种架构非常适合需要高可用性和弹性扩展的分布式系统。
12 4
|
4天前
|
负载均衡 应用服务中间件 nginx
基于Nginx和Consul构建自动发现的Docker服务架构——非常之详细
通过使用Nginx和Consul构建自动发现的Docker服务架构,可以显著提高服务的可用性、扩展性和管理效率。Consul实现了服务的自动注册与发现,而Nginx则通过动态配置实现了高效的反向代理与负载均衡。这种架构非常适合需要高可用性和弹性扩展的分布式系统。
16 3
|
4天前
|
存储 缓存 Java
Java应用瘦身记:Docker镜像从674MB优化至58MB的实践指南
【10月更文挑战第22天】 在容器化时代,Docker镜像的大小直接影响到应用的部署速度和运行效率。一个轻量级的Docker镜像可以减少存储成本、加快启动时间,并提高资源利用率。本文将分享如何将一个Java基础Docker镜像从674MB缩减到58MB的实践经验。
11 1
|
9天前
|
jenkins 测试技术 持续交付
Docker最佳实践:构建高效的CI/CD流水线
【10月更文挑战第17天】在现代软件开发实践中,持续集成(Continuous Integration, CI)和持续部署(Continuous Deployment, CD)已成为提高开发效率和软件质量的重要手段。Docker作为一种容器技术,为构建一致且隔离的开发环境提供了强有力的支撑。本文将探讨如何利用Docker来优化CI/CD流程,包括构建环境的标准化、镜像管理以及与CI/CD工具(如Jenkins、GitLab CI)的集成。
30 5
|
8天前
|
JavaScript Docker Python
下个时代的开发工具-Nix:声明式的运行环境构建器、简单场景下的docker替身
Nix 是一个独特的包管理工具和构建系统,采用声明式方法管理软件包和运行环境。它通过精确控制依赖关系和环境配置,确保软件的可重复性、隔离性和可追溯性。Nix 支持多语言开发环境,提供声明式配置、环境隔离、回滚与版本控制等核心功能,适用于复杂开发场景,有效解决依赖冲突和环境不一致问题。
|
11天前
|
Docker 容器
docker:记录如何在x86架构上构造和使用arm架构的镜像
为了实现国产化适配,需将原x86平台上的Docker镜像转换为适用于ARM平台的镜像。本文介绍了如何配置Docker buildx环境,包括检查Docker版本、安装buildx插件、启用实验性功能及构建多平台镜像的具体步骤。通过这些操作,可以在x86平台上成功构建并运行ARM64镜像,实现跨平台的应用部署。
61 2
|
15天前
|
网络协议 Docker 容器
docker pull命令拉取镜像失败的解决方案
docker pull命令拉取镜像失败的解决方案
315 0