支持 Docker / Buildpack 镜像构建

云原生buildpacks(CNB),一种再也不需要dockerfile并将源代码转换为Docker Image的标准。

SpringBoot 2.3 开启方式

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
      <layers>
        <enabled>true</enabled>
      </layers>
    </configuration>
  </plugin>
bootJar {
	layered()
}

概述

  1. 分层jar 的思想:根据规则把jar 细分。
  2. SpringBoot 继承这个思想发布**「layertools」** 工具,该功能集成进了**「org.springframework.boot」**插件

分析过程

  1. 新建一个最简单的SpringBoot2.4 项目

  2. bootJar 后解压

    ├── BOOT-INF
    │   ├── classes
    │   ├── classpath.idx
    │   ├── layers.idx
    │   └── lib
    ├── META-INF
    │   └── MANIFEST.MF
    └── org
        └── springframework
    
    layers.idx 内容
    - "dependencies":
      - "BOOT-INF/lib/"
    - "spring-boot-loader":
      - "org/"
    - "snapshot-dependencies":
    - "application":
      - "BOOT-INF/classes/"
      - "BOOT-INF/classpath.idx"
      - "BOOT-INF/layers.idx"
      - "META-INF/"
    
    MANIFEST.MF 内容
    Manifest-Version: 1.0
    Main-Class: org.springframework.boot.loader.JarLauncher
    Start-Class: com.vector.layerjar.LayerjarApplication
    Spring-Boot-Version: 2.4.0
    Spring-Boot-Classes: BOOT-INF/classes/
    Spring-Boot-Lib: BOOT-INF/lib/
    Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
    Spring-Boot-Layers-Index: BOOT-INF/layers.idx
    

    可见,划分为4 层

    • dependencies 依赖层,项目所以依赖的第三方库,release 版本的
    • spring-boot-loader 加载层,用于jar加载程序类,SpringBoot 的高级加载
    • snapshot-dependencies 快照依赖层,可能经常升级的依赖
    • application 应用层,自己写的代码和资源
  3. 打包成docker 镜像

    # 基础镜像, 需要的环境就是JDK
    FROM jboss/base-jdk:11 as builder
    
    # 使用root 操作
    USER root
    
    # 工作目录
    WORKDIR /usr/local/owl
    
    ARG JAR_FILE=./build/libs/layerjar-1.0.0.jar
    
    COPY ${JAR_FILE} app.jar
    
    RUN java -Djarmode=layertools -jar app.jar extract
    
    FROM jboss/base-jdk:11
    
    # 使用root 操作
    USER root
    
    # 工作目录
    WORKDIR /usr/local/owl
    
    # 分层复制class,jar 文件
    COPY --from=builder /usr/local/owl/dependencies/ ./
    COPY --from=builder /usr/local/owl/spring-boot-loader/ ./
    COPY --from=builder /usr/local/owl/snapshot-dependencies/ ./
    COPY --from=builder /usr/local/owl/application/ ./
    
    ENV PARAMS=""
    
    # 运行jar 文件
    ENTRYPOINT [ "sh", "-c", "java $PARAMS -Dfile.encoding=UTF-8 org.springframework.boot.loader.JarLauncher" ]
    
    # 编译
    docker build . --tag layerjar
    
    # 运行docker run -p 80:80 -e PARAMS="-Dserver.port=80" -it layerjar 
    
      .   ____          _            __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::                (v2.4.0)
    
    2020-11-16 10:34:03.267  INFO 1 --- [           main] com.vector.layerjar.LayerjarApplication  : Starting LayerjarApplication using Java 11.0.1 on a35a3c9d0ef1 with PID 1 (/usr/local/owl/BOOT-INF/classes started by root in /usr/local/owl)
    2020-11-16 10:34:03.274  INFO 1 --- [           main] com.vector.layerjar.LayerjarApplication  : No active profile set, falling back to default profiles: default
    2020-11-16 10:34:05.761  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 80 (http)
    2020-11-16 10:34:05.782  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2020-11-16 10:34:05.783  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.39]
    2020-11-16 10:34:05.925  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2020-11-16 10:34:05.929  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2452 ms
    2020-11-16 10:34:06.400  INFO 1 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
    2020-11-16 10:34:06.924  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 80 (http) with context path ''
    2020-11-16 10:34:06.954  INFO 1 --- [           main] com.vector.layerjar.LayerjarApplication  : Started LayerjarApplication in 4.838 seconds (JVM running for 5.741)
    2020-11-16 10:34:10.655  INFO 1 --- [p-nio-80-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
    2020-11-16 10:34:10.656  INFO 1 --- [p-nio-80-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
    2020-11-16 10:34:10.659  INFO 1 --- [p-nio-80-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 2 ms
    

自定义分层

实际的项目中,常常拆分成多个项目,打包成jar相互依赖,这些jar 也是经常改变的。

那么这些jar 包就应该移到snapshot-dependencies,application 或在application 中间再加一层

# 基础镜像, 需要的环境就是JDK
FROM jboss/base-jdk:11 as builder
...
# 特殊处理自定义的依赖
RUN mkdir -p ./snapshot-dependencies/BOOT-INF/lib
RUN mv ./dependencies/BOOT-INF/lib/OwlCommons-*.jar ./snapshot-dependencies/BOOT-INF/lib/

FROM jboss/base-jdk:11
...
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐