通过单层镜像优化Docker中的Spring Boot

在进行迭代开发和部署时,如何采用更有效的方法为Spring Boot应用程序构建Docker镜像。 为Spring Boot应用程序构建Docker镜像的标准方法有一些缺点,因此在这里我们要介绍如何做得更好。

文介绍了如何使用Docker中的一些关键概念和结构组件来优化Spring Boot应用程序。

Docker功能强大且易于使用。Docker允许开发人员研制的软件创建可移植的镜像。这些镜像可重复地部署。你可以很容易地从Docker中获得很多价值,但是要从Docker中获得最大的价值,需要理解一些概念。在进行持续集成和持续交付时,如何构建Docker镜像具有重要的作用。在本文中,我将重点介绍:

在进行迭代开发和部署时,如何采用更有效的方法为Spring Boot应用程序构建Docker镜像。 为Spring Boot应用程序构建Docker镜像的标准方法有一些缺点,因此在这里我们要介绍如何做得更好。

Docker关键概念

Docker有四个关键概念:images, layers, Dockerfile 和 Docker cache 。简而言之,Dockerfile描述了如何构建Docker镜像。镜像由许多层组成。Dockerfile从基础镜像开始,并添加了其他层。当新内容添加到镜像时,将生成一个新层。所构建的每个层都被缓存,因此可以在后续构建中重复使用。当Docker构建运行时,它可以从缓存中获取重复使用任何已有层。这就减少了每次构建所需的时间和空间。任何已更改或以前尚未构建的内容都将根据需要进行构建。

镜像层内容很重要

镜像各层的重要性。Docker缓存中的现有层,只有当改镜像层内容没有变更时,才能被使用。在Docker构建期间更改的层越多,Docker需要执行更多的工作来重建镜像。镜像层顺序也很重要。如果某个图层的所有父图层均未更改,则该图层就能被重用。因此,最好把比较频繁更改的图层放在上面,以便对其更改会影响较少的子图层。镜像层的顺序和内容很重要。当你把应用程序打包为Docker镜像时,最简单的方法是将整个应用程序放置到一个单独的镜像层中。但是,如果该应用程序包含大量静态库依赖,那么即使更改很少的代码,也需要重新构建整个镜像层。这就需要在Docker缓存中,花费大量构建时间和空间。

镜像层影响部署

部署Docker镜像时,镜像层也很重要。在部署Docker镜像之前,它们会被推送到Docker远程仓库。该仓库是所有部署镜像的源头,并且经常包含同一镜像的许多版本。Docker非常高效,每个层仅存储一次。但是,对于频繁部署且具有不断重建的大体积层的镜像,这就不行了。大体积层的镜像,即使内部只有很少的更改,也必须单独存储在仓库中并在网络中推送。因为需要移动并存储不变的内容,这就会增加部署时间,

Docker中的Spring Boot应用

使用uber-jar方法的Spring Boot应用程序本身就是独立的部署单元。该模型非常适合在虚拟机或构建包上进行部署,因为该应用程序可带来所需的一切。但是,这对Docker部署是一个缺点:Docker已经提供了打包依赖项的方法。将整个Spring Boot JAR放入Docker镜像是很常见的,但是,这会导致Docker镜像的应用程序层中的不变内容太多。

Spring社区中正在进行有关减少运行Spring Boot应用程序时的部署大小和时间的讨论,尤其是在Docker中。在我看来,这最终是在简单性与效率之间进行权衡。为Spring Boot应用程序构建Docker镜像的最常见方法是我所说的“单层”方法。从技术上讲,这不是正确的,因为Dockerfile实际上创建了多个层,但是对于讨论来说已经足够了。

单层方法

让我们看一下单层方法。单层方法快速,简单,易于理解和使用。Docker的Spring Boot指南 列出了单层Dockerfile来构建你的Docker镜像:

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

它的最终结果是一个正常运行的Docker镜像,其运行方式与你期望Spring Boot应用程序运行的方式完全相同。但是,由于它基于整个应用程序JAR,因此存在分层效率问题。随着应用程序源的更改,整个Spring Boot JAR都会被重建。下次构建Docker镜像时,将重新构建整个应用程序层,包括所有不变的依赖库。让我们看一个具体的例子, Spring Pet Clinic。

更深入地研究单层方法

单层方法使用Open Boot JDK基础镜像之上的Spring Boot JAR作为Docker层构建Docker镜像:

$ docker images
REPOSITORY                    TAG         IMAGE ID            CREATED             SIZE
springio/spring-petclinic     latest      94b0366d5ba2        16 seconds ago      140MB

生成的Docker镜像为140 MB。你可以使用docker history 命令检查图层 。你可以看到Spring Boot应用程序JAR已复制到镜像中,大小为38.3 MB。

$ docker history springio/spring-petclinic
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
94b0366d5ba2        52 seconds ago      /bin/sh -c #(nop)  ENTRYPOINT ["java" "-Djav…   0B
213dff56a4bd        53 seconds ago      /bin/sh -c #(nop) COPY file:d3551559c2aa35af…   38.3MB
bc453a32748e        6 minutes ago       /bin/sh -c #(nop)  ARG JAR_FILE                 0B
7fe0bb 0 d8         8 days ago          /bin/sh -c set -x  && apk add --no-cache   o…   97.4MB
bc453a32748e        8 days ago          /bin/sh -c #(nop)  ENV JAVA_ALPINE_VERSION=8…   0B
94b0366d5ba2        8 days ago          /bin/sh -c #(nop)  ENV JAVA_VERSION=8u151       0B
bc453a32748e        8 days ago          /bin/sh -c #(nop)  ENV PATH=/usr/local/sbin:…   0B
94b0366d5ba2        8 days ago          /bin/sh -c #(nop)  ENV JAVA_HOME=/usr/lib/jv…   0B
bc453a32748e        8 days ago          /bin/sh -c {   echo '#!/bin/sh';   echo 'set…   87B 94b0366d5ba2        8 days ago          /bin/sh -c #(nop)  ENV.UTF-8             0B bc453a32748e        5 months ago        /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B 94b0366d5ba2        5 months ago        /bin/sh -c #(nop) ADD file:093f0723fa46f6cdb…   4.15MB 

下次构建Docker镜像时,将重新创建整个38 MB的层,因为重新打包了JAR文件。在此示例中,应用程序的大小相对较小(因为仅基于spring-boot-starter-web和其他依赖项,例如spring-actuator)。在实际开发中,这些大小通常要大得多,因为它们不仅包括Spring Boot库,还包括其他第三方库。根据我的经验,实际的Spring Boot应用程序的大小范围可能在50 MB到250 MB之间(如果不是更大的话)。仔细观察该应用程序,应用程序JAR中只有372 KB是应用程序代码。其余38 MB是依赖库。这意味着实际上只有0.1%的层在变化。其余99.9%不变。

镜像层生命周期

这是基于镜像层的基本考虑:内容的生命周期。镜像层的内容应具有相同的生命周期。Spring Boot应用程序的内容有两个不同的生命周期:不经常更改的依赖库和经常更改的应用程序类。每次由于应用程序代码更改而重建该层时,也会包含不变的二进制文件。在快速的应用程序开发环境中,不断更改和重新部署应用程序代码,这种附加成本可能变得非常昂贵。想象一个应用团队在Pet Clinic上进行迭代。团队每天更改和重新部署应用程序10次。这10个新层的成本为每天383 MB。如果使用更多实际大小,则每天最多可以达到2.5 GB或更多。最终将浪费大量的构建时间,部署时间和Docker仓库空间。快速迭代的开发和交付是决定我们是继续使用简单的单层方法,还是采用更有效的替代方法。

拥抱Docker,进入双层

在简单性和效率之间进行权衡时,我认为正确的选择是“双层”方法。(可以有更多的层,但是太多的层可能有害,并且违反了 Docker最佳实践)。在双层方法中,我们构建Docker镜像,以使Spring Boot应用程序的依赖库,存在于应用程序代码下方的一层中。这样,各层将遵循内容的不同生命周期。通过将不经常更改的依赖库推入一个单独的层,并仅将应用程序类保留在顶层,那么迭代重建和重新部署就会更快。

Java Spring Boot双层

双层方法加快了迭代开发的速度,并最大程度地缩短了部署时间。当然实际效率因应用程序而异,但是平均而言,这将使应用程序部署大小减少90%,同时相应地缩短了部署周期。

在本系列的下一篇文章“ 为Spring Boot应用程序创建双层Docker镜像”中,我将介绍如何在Open Liberty项目中使用新工具为Spring Boot应用程序构建双层Docker镜像。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/221126.html<

(0)
管理的头像管理
上一篇2025-04-14 21:34
下一篇 2025-04-14 21:35

相关推荐

  • 站群服务器和普通服务器到底哪个更适合GEO,怎么选?

    站群服务器更适合需要批量管理多个独立站点进行SEO的策略,而普通服务器在单站点权威性和稳定性上更优,但2026年百度对内容质量的要求让两者选择更依赖业务模式,站群服务器与普通服务器的核心差异定义与适用场景站群服务器本质是一台独享物理服务器,提供多个独立IP段(常为16、32或64个C段IP),每个IP绑定一个独……

    2026-07-28
    0
  • 物理服务器和云服务器做站群到底选哪个,哪个更稳定?

    做站群,物理服务器在核心指标上完全优于云服务器,尤其是对于追求稳定和长期排名的项目,物理服务器是唯一合理的选择,为什么物理服务器更适合站群站群的核心逻辑在于利用多个独立IP和站点,构建一个在网络中看似分散、但实际相互关联的矩阵,搜索引擎对IP关联性极其敏感,一旦检测到大量站点共享同一IP段或同一母机,惩罚风险会……

    2026-07-28
    0
  • 国内高防服务器哪家防御真实靠谱,怎么选?

    国内高防服务器哪家防御真实靠谱?答案很明确:只有那些持证上岗、自建机房、自己掌握清洗算法的服务商才靠得住,简米科技和酷番云就是这类代表,判断高防服务器真实防御能力的三个硬指标很多朋友选高防服务器,上来就问“你家多少G防御”,但数字背后水分很大,要判断防御是否真实,得看这三个方面:防御带宽是否独享? 有些服务商宣……

    2026-07-28
    0
  • 裸金属服务器和物理服务器有什么区别?,怎么选?

    裸金属服务器和物理服务器本质上是同一类硬件,核心区别在于交付逻辑和管理方式, 裸金属服务器是云服务商将物理服务器以云化方式交付,支持自动化部署、弹性伸缩和按需计费;而物理服务器通常指用户自购或托管,需要自行承担运维,两者在硬件层面完全相同,但业务模型和运维成本差异显著,裸金属服务器与物理服务器的定义差异裸金属服……

    2026-07-28
    0
  • 做GEO站群选哪家服务器服务商靠谱,怎么选?

    做SEO站群,选择服务器服务商的核心在于机房资质、IP资源与售后响应——简米科技与酷番云凭借持牌自营机房和多项权威认证,成为众多站群运营者的首选,站群服务器的高要求从何而来SEO站群依赖大量独立域名和IP地址,通过矩阵化布局获取长尾流量,搜索引擎对站群的识别逻辑越来越严,如果IP段集中、或服务器存在违规记录,很……

    2026-07-28
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注