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

admin 2026-04-21 04:11:46 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档探索了SpringBoot程序打包Docker镜像的四种方式:默认方式337M、GraalVM方式123M、OpenJDK基础镜像505M、jlink+Alpine方式93M。测试发现GraalVM不仅镜像小且内存占用仅为传统方式的1/4,建议新JDK25项目优先采用GraalVM,旧项目可使用jlink定制JRE方案。 综合评分: 75 文章分类: 云安全,应用安全,安全工具,解决方案,技术标准


cover_image

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

原创

一只岸上的鱼 一只岸上的鱼

一只岸上的鱼

2026年3月20日 16:38 江苏

在小说阅读器读本章

去阅读

缘起

云计算时代的来临,有一门被誉为云计算伴生编程语言: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 world

package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;
@RestControllerclass HelloController {    @GetMapping("/hello")    String sayHello(){        return "hello 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 {id 'java'id 'org.springframework.boot' version '4.0.3'id 'io.spring.dependency-management' version '1.1.7'    //id 'org.graalvm.buildtools.native' version '0.11.4'}

使用命令打包:

./gradlew bootBuildImage --imageName=hello:normal

大小337M,同时也可以看到打包下载的基础镜像:

方式二: 默认配置graalvm打包

加入graalvm的配置(方式一注释调的部分),打包:

./gradlew bootBuildImage --imageName=hello:gralvm

大小123M:

方式三: 手工打包,使用标准openjdk镜像为基础

所谓手工打包,就是自己写dockerfile,自己设置基础镜像,先试试默认情况下常用的openjdk镜像

FROM openjdk:25-jdk-slim
WORKDIR /appRUN useradd -U springUSER spring:springCOPY build/libs/*.jar app.jar
EXPOSE 8080CMD ["java", "-jar", "app.jar"]

打包命令:

docker build -t hello:openjdk -f deploy/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 \         --compress=2 \         --output /optimized-jdk-25
FROM alpine:latestENV JAVA_HOME=/opt/jdk/jdk-25ENV PATH="${JAVA_HOME}/bin:${PATH}"
COPY --from=jre-builder /optimized-jdk-25 $JAVA_HOME
RUN addgroup --system spring && adduser --system spring --ingroup spring
RUN mkdir /app && chown -R $APPLICATION_USER /appCOPY --chown=spring:spring build/libs/*.jar /app/app.jarWORKDIR /appUSER springEXPOSE 8080ENTRYPOINT [ "java", "-jar", "/app/app.jar" ]

构建命令:

docker build -t hello:alpine -f deploy/jlink.Dockerfile .

大小: 93M

有点不放心,跑一下试试:

docker run -it -p 8080:8080 hello:alpine

访问一下:

一切正常!

小结

以上只是比较了打包大小的不同,这对graalvm是不公平的,毕竟他的特点是增强 AOT(Ahead-of-Time)编译,降低内存占用,提高启动时间,还是得测试一下:

docker run -it -p 8080:8080 --name alpine hello:alpinedocker run -it -p 9090:8080 --name graalvm hello:graalvmdocker stats

看到资源占用:

graalvm的内存占用不到原始java代码的1/4!

所以:

1、对应新的项目,高版本jdk项目,尤其是最新的25版本,完全可以考虑以graalvm来编译打包

2、对应旧的项目,或者低版本jdk的项目,生产环境使用alpine定制jre的方式,就是方式4,测试环境就使用默认openjdk:毕竟包含了大量的工具,方便调测。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:一只岸上的鱼 一只岸上的鱼 一只岸上的鱼《探索springboot程序打包docker的最佳方式》

评论:0   参与:  0