背景

在我们实际生产容器化部署过程中,往往会遇到 Docker 镜像很大,部署发布很慢的情况

影响 docker 镜像大小的因素,主要有以下三个方面:

    1. 基础镜像的大小 。尽量选择 aphine 作为基础镜像 减少操作系统内置软件
    1. Dockerfile 指令层数。 这就要求我们优化 Dockerfile 能合并在一行的尽量合并等
    1. 应用 jar 的大小。这是今天要分享的重点内容

helloworld 镜像

我们先来基于 spring boot 2.3.0 构建一个最简单的 web helloworld,然后构建镜像。

FROM adoptopenjdk:11-jre-hotspot as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
ENTRYPOINT ["java", "-jar application.jar"]
docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar  . -t demo:v1.0

查看镜像分层信息

我们通过 docker inspect demo:v1.0 来看下此镜像的每层的散列值

// demo:v1.0 版本镜像分层信息摘要
"Layers": [
"sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e",
"sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6",
"sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794",
"sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233",
"sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab",
"sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d",
"sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535",
"sha256:b87d2ff74819f83038ea2f89736a19cfcf99bfa080b8017d191c900a09a7524f"
]

helloworld 升级重新构建

我们对 helloworld 程序进行部分修改(模拟开发过程),然后重新构建镜像

docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar  . -t demo:v1.1

此时镜像分层信息如下 docker inspect demo:v1.1

// demo:v1.1 版本镜像分层信息摘要
"Layers": [
"sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e",
"sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6",
"sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794",
"sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233",
"sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab",
"sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d",
"sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535",
"sha256:c1b6350d545fea605e0605c4bfd7f4529cfeee3f6759750d6a5ddeb9c882fc8f"
]

比较 v1.0、v1.1 镜像

通过比较 v1.0 和 v1.1 版本的镜像摘要信息,我们会发现只有最后的一层发生了变化,我们通过 Dive 是一个用 Go 语言编写的 Docker 镜像分析工具 来确定一下 最后一层是做了哪些事情

dive demo:v1.0,大家会看到是最后的 jar 不一样 导致 16M 的内容需要重新构建,当你的业务 jar 很大时,这块就是性能瓶颈

spring boot 默认打包解密

默认情况下,spring boot 构建出来的 jar ,解压后可以看到如下目录结构。默认会当做一个整体 ,在构建镜像时作为一个单独层,没有区分业务 classes 和 引用的第三方 jar

META-INF/
MANIFEST.MF
org/
springframework/
boot/
loader/
BOOT-INF/
classes/
lib/

layer jar

通过上文大家就可以知道分层 jar 的思想就是把,jar 再根据规则细分,业务 class 和 三方 jar 分别对应镜像的不同层,这样改动业务代码,只需变动很少的内容 提高构建速度。

开启分层打包

  <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>

编写支持分层 Dockerfile

核心是通过 spring boot 提供的 layertools 工具,将 jar 进行拆分 然后通过 COPY 指令去分别加载

FROM adoptopenjdk:11-jre-hotspot as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM adoptopenjdk:11-jre-hotspot
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

构建新镜像并查看分层信息

docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar  . -t demo:v2.0
"Layers": [
"sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e",
"sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6",
"sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794",
"sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233",
"sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab",
"sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d",
"sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535",
"sha256:06fe18cf8ae7384f120f2c6a3a33b31999dd0460cf1edae45e8f13adeab35942",
"sha256:16cf814564b8a667fcc9f07314b6084cbef8dc8c0a6565c7a2d91d74faf7e7de",
"sha256:94be40f716016b68cdd6b99d2cb8154acf8475c3a170a898a22f95a8ef40ffd3",
"sha256:427d87d6a5fe6da13cb4233939c3a1ff920bc6b4d2f14b5d78af7aef98fda7de"
]

修改代码部分业务代码,重新构建

docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar  . -t demo:v2.1
"Layers": [
"sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e",
"sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6",
"sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794",
"sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233",
"sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab",
"sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d",
"sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535",
"sha256:06fe18cf8ae7384f120f2c6a3a33b31999dd0460cf1edae45e8f13adeab35942",
"sha256:16cf814564b8a667fcc9f07314b6084cbef8dc8c0a6565c7a2d91d74faf7e7de",
"sha256:94be40f716016b68cdd6b99d2cb8154acf8475c3a170a898a22f95a8ef40ffd3",
"sha256:8a20c60d361696a4e480fb6fbe1daf8b88bc54c579a98e209da1fb76e25de5aa"
]

查看区别层镜像

最后一层变动大小为 5KB

总结

项目推荐: Spring Cloud 、Spring Security OAuth2的RBAC权限管理系统 欢迎关注

原创 Spring Boot 2.3 新特性分层JAR的更多相关文章

  1. Spring Boot 2(一):Spring Boot 2.0新特性

    Spring Boot 2(一):Spring Boot 2.0新特性 Spring Boot依赖于Spring,而Spring Cloud又依赖于Spring Boot,因此Spring Boot2 ...

  2. Spring Boot 2.0 新特性和发展方向

    以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...

  3. 【2.0新特性】Spring Boot 2.0新特性

    以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...

  4. Spring Boot实践——Spring Boot 2.0 新特性和发展方向

    出自:https://mp.weixin.qq.com/s/EWmuzsgHueHcSB0WH-3AQw 以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Jav ...

  5. Spring Boot 2.0 新特性

    这是一篇总结文章,主要收集 Spring Boot 2.0 相对于 Spring Boot 1.x 的新特性,本章节并不提供实践性质的源代码.在 Spring Boot 系列文章中会持续退出实践章节. ...

  6. 「Spring Boot 2.4 新特性」一键构建Docker镜像

    背景 在我们开发过程中为了支持 Docker 容器化,一般使用 Maven 编译打包然后生成镜像,能够大大提供上线效率,同时能够快速动态扩容,快速回滚,着实很方便.docker-maven-plugi ...

  7. Spring Boot 2.3 新特性优雅停机详解

    什么是优雅停机 先来一段简单的代码,如下: @RestController public class DemoController { @GetMapping("/demo") p ...

  8. 『Spring Boot 2.4新特性』减少95%内存占用

    节省 95%的内存占用,减少 80%的启动耗时. GraalVM 是一种高性能的虚拟机,它可以显著的提高程序的性能和运行效率,非常适合微服务.最近比较火的 Java 框架 Quarkus 默认支持 G ...

  9. 「Spring Boot 2.4 新特性」启动耗时详细监控

    背景 Spring Boot 项目随着项目开发过程中引入中间件数量的增加,启动耗时 逐渐增加. 笔者在 <Spring Boot 2.4.0 正式 GA,全面拥抱云原生>文章评论下发现了 ...

随机推荐

  1. css故障文字动画

    免费分享95套java实战项目,不仅有源码还有对应的开发视频,关注公众号『勾玉技术』回复"95"即可获取 首先给内容上hover和before, .glitch:hover:bef ...

  2. Error running 'tomcat': Unknown error

    免费分享95套java实战项目,不仅有源码还有对应的开发视频,关注公众号『勾玉技术』回复"95"即可获取 无意中发现了一位清华大佬的算法笔记,需要的加公众号 勾玉技术 回复 清华算 ...

  3. ElasticSearch URI 查询

    公号:码农充电站pro 主页:https://codeshellme.github.io 1,URI 查询格式 URI 查询的一般格式如下: GET /index_name/_search?q=key ...

  4. JavaScriptBOM操作

    BOM(浏览器对象模型)主要用于管理浏览器窗口,它提供了大量独立的.可以与浏览器窗口进行互动的功能,这些功能与任何网页内容无关.浏览器窗口的window对象是BOM的顶层对象,其他对象都是该对象的子对 ...

  5. sql注入和union all关联查询的学习总结

    1.后台从页面取值进行sql查询时最好不要直接拼,如下代码: String sql = "SELECT wo.* " + " from push_command pu & ...

  6. 基于docker搭建DNSmasq

    一.概述 DNSmasq是一个小巧且方便地用于配置DNS和DHCP的工具,适用于小型网络,它提供了DNS功能和可选择的DHCP功能.它服务那些只在本地适用的域名,这些域名是不会在全球的DNS服务器中出 ...

  7. Linux下搭建RocketMQ环境

    Apache 官网: http://rocketmq.apache.org/ RocketMQ 的 Github 地址: English:https://github.com/apache/rocke ...

  8. 基于云原生DevOps服务自动化部署前端项目学习总结

    本文主要以部署前端Vue项目为例,讲述了如何基于云原生DevOps服务自动化部署前端项目~从开发完成到线上环境,我们只需提交代码即可~ 一.引言 作为一名开发人员,日常工作中我们除了需要负责代码的开发 ...

  9. mock 请求分发

    首发于 语雀文档 背景是这样的 我们公司的后管项目走的不是 resful 风格的 api,而是走后管网关,后管网关会将请求进行分发,具体怎么分发,有这么以下几点: 请求全部走 POST 请求 URL ...

  10. Oracle数据库搬家牵扯出的一些知识点记录

    Oracle数据库迁移过程中的一些记录 工作原因,对开发服务器的数据库进行了迁移,实际执行操作之前查了一下迁移oracle数据库的可行方案,最后用了 exp/imp 进行导出导入(这个比较简单),以及 ...