• Docker镜像分层
  • SpringBoot 2.3.x 新增对分层的支持
    • spring-boot-maven-plugin开启分层编译支持
    • Dockerfile修改
    • 分层后的Jar结构
      • classpath.idx: 文件列出了依赖的 jar 包列表,到时候会按照这个顺序载入。
      • layers.idx: 文件清单,记录了所有要被复制到 Dokcer 镜像中的文件信息。
    • 列出可以从分层 Jar 中提取出的文件夹信息(spring-boot-jarmode-layertools)
java -Djarmode=layertools -jar isuwang-mobile-oss-1.0.jar  list


dependencies   -- 依赖项一般变化不大
spring-boot-loader  -- spring-boot启动模块
snapshot-dependencies   -- 快照依赖,为快照版本的依赖,更新迭代的会快一些
application  -- 业务层,也就是我们最频繁变动的
  • 构建速度的测试
    普通构建 分层构建
    全构建 3m41s 3m58s
    修改代码后构建 2m24s 2m54s
    修改api后构建 1m58s 3m31s
主要耗时步骤(154m -> 耗时  1m7s / 1m37s   )
Step 4/16 : COPY demo-1.0.jar application.jar

(耗时 25s)
Step 5/16 : RUN java -Djarmode=layertools -jar application.jar extract

总结

  • 镜像构建 :  在构建上,使用分层 Jar 构建镜像可能比普通方式构建镜像更繁琐(构建两次,还要解压),所以也更耗时,故而在构建上分层 Jar 构建镜像没有优势,甚至处于劣势
  • 镜像推送 : 在推送上,如果每次构建镜像都只是修改构建镜像项目的源码,使用分层 Jar 构建镜像,可以大大加快镜像推送速度。如果是修改构建镜像项目中的依赖包,则和普通构建一样速度很慢(因为dependencies层是中间层镜像最大的一层)
  • 镜像拉取 : 与推送一样
  • 综上,在本地构建方面,普通构建有优势;在网络传输方面(docker pull/docker push),分层构建有优势

最后附上实验用的dockerfile

#FROM openjdk:8u212-jdk-alpine3.9  
#MAINTAINER fa "fa@x.com.cn"  
## 1.普通镜像构建脚本文件  
## 系统编码  
#ENV LANG=C.UTF-8 LC_ALL=C.UTF-8  
#RUN apk add --no-cache bash  
## 设置时区为上海  
#RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && apk del tzdata  
#VOLUME /tmp  
#ADD demo-1.0.jar app.jar  
#EXPOSE 8099  
#ENTRYPOINT exec  java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar  
  
  
  
# 2. 分层镜像构建脚本文件  
# 指定基础镜像,这是分阶段构建的前期阶段  
FROM openjdk:8u212-jdk-alpine3.9 as builder  
MAINTAINER fa "fa@x.com.cn"  
# 执行工作目录  
WORKDIR application  
# 配置参数  
#ARG JAR_FILE=target/*.jar  
# 将编译构建得到的jar文件复制到镜像空间中(主要的耗时步骤)  
COPY application.jar application.jar  
# 通过工具spring-boot-jarmode-layertools从application.jar中提取拆分后的构建结果  
RUN java -Djarmode=layertools -jar application.jar extract  
  
# 正式构建镜像  
FROM openjdk:8u212-jdk-alpine3.9  
#系统编码  
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8  
RUN apk add --no-cache bash  
# 设置时区为上海  
RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && apk del tzdata  
EXPOSE 8080  
EXPOSE 9595  
WORKDIR application  
# 前一阶段从jar中提取除了多个文件,这里分别执行COPY命令复制到镜像空间中,每次COPY都是一个layer  
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"]  
ENTRYPOINT exec  java ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher