探索springboot程序打包docker的最佳方式

探索springboot程序打包docker的最佳方式 探索springboot程序打包docker的最佳方式缘起云计算时代的来临有一门被我誉为云计算伴生的编程语言golang其与docker的天生的搭配开启了云计算的黄金时代。然而java确实一门不服老的语言不断的进化着springboot 4 和spring 7的发布尤其是springboot4 GraalVM 25 直接从实验特性转向了生产。虚拟线程常态化也是值得学习的特性。加上还有很多的老的项目还在用springboot技术所以想把java的整个技术栈再捡起来学习一遍后续会陆续写一些关于springboot4 、jkd 25 lts的一些文。学到哪儿就写到哪儿今天想试试springboot程序打包docker的几种方式的大小区别探索一下最佳的方式开始准备一个最简单的restful的程序使用spring initializr 生成项目基础配置如下注意2点1、java 25 2、加入graalvm一个hello worldpackagecom.example.demo.controller;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;RestControllerclassHelloController{GetMapping(/hello)StringsayHello(){returnhello world!;}}显示编译一下代码看看原始jar包有多大./gradlew build一个包含mvc基本程序的一个hello world大小79M方式一全默认方式的打包镜像不做任何更多的配置只使用springboot 4 和gradle的默认配置根据资料springboot的默认使用paketobuildpacks/builder-jammy-tiny 镜像这是一个以ubuntu 22为基础的镜像大小50-70M注意犹豫我们生成项目配置的时候加入了graalm支持必须先注释调否则默认会使用graal技术build.gradle 文件部分plugins{idjavaid org.springframework.boot version4.0.3id io.spring.dependency-management version1.1.7//id org.graalvm.buildtools.native version 0.11.4}使用命令打包./gradlew bootBuildImage--imageNamehello:normal大小337M同时也可以看到打包下载的基础镜像方式二 默认配置graalvm打包加入graalvm的配置方式一注释调的部分打包./gradlew bootBuildImage--imageNamehello:gralvm大小123M:方式三 手工打包使用标注openjdk镜像为基础所谓手工打包就是自己写dockerfile自己设置基础镜像先试试默认情况下常用的openjdk镜像FROM openjdk:25-jdk-slim WORKDIR /app RUN useradd -U spring USER spring:spring COPY build/libs/*.jar app.jar EXPOSE 8080 CMD [java, -jar, app.jar]打包命令dockerbuild-thello:openjdk-fdeploy/openjdk.Dockerfile.大小505M方式四 手工打包使用jlink构建一个最小的运行jre环境以alpine为基础虽然现在的java不再单独提供jre环境了但是可以通过jlink构建一个程序所需的最小运行环境然后部署到alpine linux上FROM eclipse-temurin:25-jdk-alpine AS jre-builder RUN apk update apk add binutils RUN $JAVA_HOME/bin/jlink \ --verbose \ --add-modules java.base \ --strip-debug \ --no-man-pages \ --no-header-files \ --compress2 \ --output /optimized-jdk-25 FROM alpine:latest ENV JAVA_HOME/opt/jdk/jdk-25 ENV PATH${JAVA_HOME}/bin:${PATH} COPY --fromjre-builder /optimized-jdk-25 $JAVA_HOME RUN addgroup --system spring adduser --system spring --ingroup spring RUN mkdir /app chown -R $APPLICATION_USER /app COPY --chownspring:spring build/libs/*.jar /app/app.jar WORKDIR /app USER spring EXPOSE 8080 ENTRYPOINT [ java, -jar, /app/app.jar ]构建命令dockerbuild-thello:alpine-fdeploy/jlink.Dockerfile.大小 93M有点不放心跑一下试试dockerrun-it-p8080:8080 hello:alpine访问一下一切正常小结以上只是比较了打包大小的不同这对graalvm是不公平的毕竟他的特点是增强 AOTAhead-of-Time编译降低内存占用提高启动时间还是得测试一下dockerrun-it-p8080:8080--namealpine hello:alpinedockerrun-it-p9090:8080--namegraalvm hello:graalvmdockerstats看到资源占用graalvm的内存占用不到原始java代码的1/4所以1、对应新的项目高版本jdk项目尤其是最小的25版本完全可以考虑以graalvm来编译打包2、对应旧的项目或者低版本jdk的项目生产环境使用alpine定制jre的方式就是方式4测试环境就使用默认openjdk毕竟包含了大量的工具方便调测。欢迎关注探索springboot程序打包docker的最佳方式