体验springboot服务docker打包分层

前言

随着云原生技术的发展,现在大部分企业项目都通过容器化来部署项目,不管是docker部署还是k8s都离不开打镜像的环节,传统打镜像的方式通常时间上会比较漫长,有时候改动少量代码就需要全部打包。今天来体验一下Springboot2.3.0后的分层打包功能。

普通打包

我们先新建一个添加了springboot依赖的maven测试项目,对于诸位老Javaboy来说属于闭着眼操作了,默认的maven项目里一般不会自动添加上打包插件。最开始接触springboot的时候使用maven package打出来jar包启动会发现报错找不到入口类。

所以一定要在pom中加上

xml 复制代码
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <mainClass>com.uptown.sign.SignApplication</mainClass>
                <layout>ZIP</layout>
                <fork>true</fork>
                <addResources>true</addResources>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

随便写一个hello world的控制器入口,然后直接编写Dockerfile文件

bash 复制代码
FROM openjdk:8-jdk-alpine

# 打包命令
RUN mvn package
# 声明一个端口但不真正运行在这个端口
EXPOSE 8080
# 把打出来的包添加到镜像中
ADD target/*.jar ./app.jar
# 执行命令
CMD java -jar app.jar

完事之后运行命令打成镜像测试

bash 复制代码
docker build . -t test:0.0.1

打出镜像后查看镜像的分层结构。

bash 复制代码
docker inspect test:0.0.1

图中的Layers就是镜像层,docker是会按命令分层,我们把hello world改成fuck work,重新执行下上述步骤再docker inspect分析下新镜像的Layers会发现

你会发现这些Layers中只有最后一处与旧镜像内容不一样,我们仅仅只改动了一个接口返回的文案,重新打包后会把所有动作重新都做一边,做完后发现打出来的镜像每层基本都一样,只有最后一层有变化,那么我们能不能只重新制作有变化的包呢。

分层打包

当然是可以了,这就是springboot在230加的新特性,虽然现在springboot版本已经出道3了,但是我认为越迭代越重,加了很多可有可无的东西,不如老版本中一些好用的特性值得把玩。

根本原理其实是一个springboot打出jar包中主要包含四个部分,自己写的代码第三方依赖SpringBoot内部配置快照依赖 ,如果仅仅只是改动了自己写的代码的话那其他那三部分根本不用变。也就是说如果你换了依赖版本那就不行了。

首先在pom中打开分层开关

xml 复制代码
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <layers>
                    <enabled>true</enabled>
                </layers>
            </configuration>
        </plugin>
    </plugins>
</build>

再用mvn package打包之后我们用命令分析下jar包内容

ini 复制代码
java -Djarmode=layertools -jar target/dockers-demo-0.0.1-SNAPSHOT.jar list

这里就分别对应了上述那四个部分代码,所以如果只更改部分代码的话并不需要再将依赖相关的代码编译上次编译完的直接用呗。

ini 复制代码
FROM openjdk:8-jdk-alpine
RUN mvn package
ADD target/*.jar ./app.jar
RUN java -Djarmode=layertools -jar app.jar extract

FROM openjdk:8-jre
WORKDIR application
# 复制第三方依赖、SpringBoot内部配置、快照依赖
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"]

改造后你再去打包会发现特别快,springboot好用就在于内置了很多依赖包,跨过依赖包单独打业务代码快的一批,但是仅在依赖版本未发生变更的场景下生效。

相关推荐
南雨北斗17 分钟前
VSCODE进行代码格式化的方法
后端
深栈解码19 分钟前
第一章:认识JVM:跨平台的引擎与生态基石
java·后端
fortify29 分钟前
Git:从0掌握Git的使用,满足日常开发需求
后端
绵阳的脑内SSD31 分钟前
Lecture #20:Database Logging
后端
AirMan31 分钟前
深入浅出Redis:一文掌握Redis底层数据结构与实现原理
redis·后端·面试
Hx__35 分钟前
限流算法
后端
_代号00738 分钟前
Go 编译报错排查:vendor/golang.org/x/crypto/cryptobyte/asn1 no Go source files
后端·go
David爱编程39 分钟前
Deployment vs StatefulSet:怎么选?
后端·云原生·kubernetes
用户92724725021941 分钟前
新闻自动采集并通过API发布到博客
前端·后端
icecreamstorm43 分钟前
MySQL 事务 最全入门
后端·mysql