SpringBoot程序打包Docker镜像的最佳方式

 更新时间:2026年03月24日 08:51:37   作者:说实话起个名字真难啊  
本文探索了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 world

package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
class 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 /app
RUN useradd -U spring
USER spring:spring
COPY build/libs/*.jar app.jar
EXPOSE 8080
CMD ["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:latest
ENV JAVA_HOME=/opt/jdk/jdk-25
ENV 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 /app
COPY --chown=spring:spring build/libs/*.jar /app/app.jar
WORKDIR /app
USER spring
EXPOSE 8080
ENTRYPOINT [ "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:alpine
docker run -it -p 9090:8080 --name graalvm hello:graalvm
docker stats

看到资源占用:

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

所以:

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

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

以上就是SpringBoot程序打包Docker镜像的最佳方式的详细内容,更多关于SpringBoot打包Docker镜像的资料请关注脚本之家其它相关文章!

相关文章

  • Docker中Mysql容器无法停止无法删除问题

    Docker中Mysql容器无法停止无法删除问题

    这篇文章主要介绍了Docker中Mysql容器无法停止无法删除问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Docker安装mysql主从复制的实现步骤

    Docker安装mysql主从复制的实现步骤

    MySQL主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点,本文主要介绍了Docker安装mysql主从复制的实现步骤,感兴趣的可以了解一下
    2024-03-03
  • Docker+nacos+seata1.3.0安装与使用配置教程

    Docker+nacos+seata1.3.0安装与使用配置教程

    这篇文章主要介绍了Docker+nacos+seata1.3.0安装与使用配置教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-07-07
  • docker build -t 和 docker build -f 区别解析

    docker build -t 和 docker build -f 区别解析

    docker build 是用于构建Docker镜像的命令,它允许你基于一个Dockerfile来创建一个镜像,在 docker build 命令中,有两个常用的选项 -t 和 -f,它们有不同的作用,这篇文章主要介绍了docker build -t 和 docker build -f 区别,需要的朋友可以参考下
    2023-08-08
  • Docker 分布式仓库 Harbor的实现

    Docker 分布式仓库 Harbor的实现

    Harbor 是一个用于存储和分发 Docker 镜像的企业级 Registry 服务器,本文就来介绍一下Docker 分布式仓库 Harbor的实现,感兴趣的可以了解一下
    2025-08-08
  • CentOS 7.5下 安装Docker 教程 详解

    CentOS 7.5下 安装Docker 教程 详解

    这篇文章主要介绍了CentOS 7.5下 安装Docker 教程 ,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-05-05
  • 删除Docker镜像、容器和卷的教程指南

    删除Docker镜像、容器和卷的教程指南

    Docker 可以轻松地将应用程序和服务封装在容器中,以便在任何地方运行,然而,在使用 Docker 的过程中,很容易积累大量未使用的镜像、容器和数据卷,这些会使输出杂乱,并占用磁盘空间,所以本文给大家介绍了如何删除Docker镜像、容器和卷,需要的朋友可以参考下
    2024-10-10
  • docker启动报错205/limit的解决方案

    docker启动报错205/limit的解决方案

    Dcoker启动报错经常能看到 205/limit这个错误提示,这是告诉你linux操作系统的文件描述符设置的和Docker的不匹配,或者是设置的比较小了,本文介绍了docker启动报错205/limit的解决方案,需要的朋友可以参考下
    2024-06-06
  • Docker数据卷持久化存储的实现

    Docker数据卷持久化存储的实现

    Docker的数据卷机制通过抽象的存储层设计,完美解决了容器生命周期与数据生命周期解耦的问题,下面就来介绍一下Docker数据卷持久化存储的实现,感兴趣的可以了解一下
    2025-09-09
  • Docker容器连接相互通信的实现

    Docker容器连接相互通信的实现

    这篇文章主要介绍了Docker容器连接相互通信的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12

最新评论