部署应用方式有很多,但是基于docker的部署是很常用的。而用docker就避免不了使用dockerfile.常见的是使用如下方式
基础版本
编写一个最常见的部署java的dockerfile
FROM openjdk:17-slim
WORKDIR /java
ADD main-module/target/toolserve-3.0.0.jar /java/app.jar
ENTRYPOINT ["java","-jar","/java/app.jar"]
EXPOSE 8081
然后构建镜像,并且指定生成的镜像名
docker build -t toolserve .
运行镜像,映射端口,最后可以看到运行成功
docker run -p 8081:8081 toolserve
这种是全量更新,我就是哪怕更改一行代码都是全量更新。所以不好
高阶版本
Spring Boot官方在Spring Boot 2.3及以后的版本中,引入了分层JAR的概念,这使得构建镜像时可以将应用程序的不同部分(如依赖项、Spring Boot启动器、快照依赖项和应用程序本身)分开到不同的层中
dockerfile如下
# 第一阶段:构建并提取分层
FROM openjdk:17-slim AS builder
WORKDIR /java
ARG JAR_FILE=main-module/target/toolserve-3.0.0.jar
COPY ${JAR_FILE} app.jar
RUN java -Djarmode=layertools -jar app.jar extract
# 第二阶段:构建最终镜像
FROM openjdk:17-slim
WORKDIR /java
COPY --from=builder /java/dependencies/ ./
COPY --from=builder /java/spring-boot-loader/ ./
COPY --from=builder /java/snapshot-dependencies/ ./
COPY --from=builder /java/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
EXPOSE 8081
原理说明
首先使用了docker的分阶段构建技术。第一阶段构建出jar。第二阶段从第一阶段获拿成品jar,有助于减少包体积,是个非常常用的优化技巧。不单单是在java有效。
第一阶段注意到增加打包的参数
-Djarmode=layertools
这个springboot的可识别一个参数,这么配后,就不会走正常的启动逻辑,而是运行一个jar分层逻辑,把jar包中内容打整理为多个部分。生成一个索引文件laryers.idx,引用了外部库的。和业务代码隔离
总结
最后优点是显而易见的
- 利用缓存:由于依赖项和启动器等不会频繁变化,因此它们可以被缓存,从而在后续的构建中节省时间。
- 减少镜像大小:通过只复制必要的文件到最终镜像中,可以减小镜像的大小。提高推送和拉取的速度。
- 提高构建速度:由于Docker可以跳过未更改层的构建步骤,因此整个构建过程会更快。
于是就发现拉从构建到推送到拉取镜像分层全部有缓存,美滋滋。
可以对比下构建时间,全量花了5秒
而改造后0.5秒就完成了
一个只改了业务层传了131b的代码。一个是和底层依赖一起传了127.72mb的。这差距简直,最后希望大家早日用上。