知識庫 / Spring / Spring Boot RSS 訂閱

GraalVM Docker 鏡像構建指南

Docker,Spring Boot
HongKong
4
11:25 AM · Dec 06 ,2025

1. 簡介

GraalVM 通過其 Ahead-Of-Time (AOT) 編譯器將 Java 應用程序編譯為機器可執行文件。這些可執行文件直接進入目標機器執行,而無需使用 Just-In-Time (JIT) 編譯器。GraalVM 生成的二進制文件更小,啓動時間更快,並且在沒有預熱的情況下提供最佳性能。此外,這些可執行文件相對於在 JVM 上運行的應用程序而言,內存佔用和 CPU 消耗更低。

Docker 允許我們將軟件組件打包為 Docker 鏡像並在 Docker 容器中運行。一個 Docker 容器包含應用程序運行所需的一切,包括應用程序代碼、運行時、系統工具和庫

在本教程中,我們將討論如何為 Java 應用程序創建 GraalVM 本地映像。然後,我們將討論如何使用此本地映像作為 Docker 鏡像並在 Docker 容器中運行它。

2. 原生鏡像是什麼?

原生鏡像是一種技術,它將 Java 代碼提前編譯成原生可執行文件。該原生可執行文件僅包含在運行時所需代碼,包括應用程序類、標準庫類、語言運行時以及來自 JDK 的靜態鏈接的本機代碼。

原生鏡像構建器(native-image)掃描應用程序類和其他元數據,以創建特定於操作系統和架構的二進制文件。 native-image 工具執行靜態應用程序代碼分析,以確定在應用程序運行時可訪問的類和方法。然後,它將所需的類、方法和資源編譯成二進制可執行文件。

3. 原生圖像的優勢

以下是原生圖像可執行文件的幾個優勢:

  • 作為原生圖像構建器,它僅編譯在運行時所需的資源,因此可執行文件的大小很小
  • 原生可執行文件具有極快的啓動時間,因為它們直接在目標機器上執行,而無需 JIT 編譯器
  • 它提供了一個更小的攻擊面,因為它只打包了所需的應用程序資源
  • 非常適合打包在輕量級容器鏡像中,例如 Docker 鏡像,以便快速高效地部署

4. 構建 GraalVM 原生鏡像

本節將為 Spring Boot 應用程序構建 GraalVM 原生鏡像。首先,我們需要安裝 GraalVM 並設置 JAVA_HOME環境變量。其次,創建一個 Spring Boot 應用程序,並添加 Spring Web 和 GraalVM Native Support 依賴項:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>3.1.5</version>
</dependency>

我們還需要添加以下插件以支持 GraalVM 運行時:

<build>
    <plugins>
        <plugin>
            <groupId>org.graalvm.buildtools</groupId>
            <artifactId>native-maven-plugin</artifactId>
            <version>0.9.27</version>
        </plugin>
    </plugins>
</build>

該應用程序包含一個示例 REST 控制器。

@RestController
class HelloController {
	
    @GetMapping
    public String hello() {
	return "Hello GraalVM";
    }
}

讓我們使用 Maven 命令構建原生可執行文件:

$mvn -Pnative native:compile

native-maven-plugin 構建 GraalVM 本地鏡像。由於 GraalVM 本地鏡像編譯器執行靜態代碼分析,因此與常規 Java 應用程序編譯相比,構建時間較高。

以下是 GraalVM 編譯的輸出:

========================================================================================================================
GraalVM Native Image: Generating 'springboot-graalvm-docker' (executable)...
========================================================================================================================
[1/8] Initializing... (42.7s @ 0.15GB)
Java version: 17.0.8+9-LTS, vendor version: Oracle GraalVM 17.0.8+9.1
Graal compiler: optimization level: 2, target machine: x86-64-v3, PGO: ML-inferred
C compiler: gcc (linux, x86_64, 11.3.0)
Garbage collector: Serial GC (max heap size: 80% of RAM)

// Omitted for clarity

[2/8] Performing analysis... [******] (234.6s @ 1.39GB)
15,543 (90.25%) of 17,222 types reachable
25,854 (67.59%) of 38,251 fields reachable
84,701 (65.21%) of 129,883 methods reachable
4,906 types, 258 fields, and 4,984 methods registered for reflection
64 types, 70 fields, and 55 methods registered for JNI access
4 native libraries: dl, pthread, rt, z
[3/8] Building universe... (14.7s @ 2.03GB)
[4/8] Parsing methods... [*******] (55.6s @ 2.05GB)
[5/8] Inlining methods... [***] (4.9s @ 2.01GB)
[6/8] Compiling methods... [**********
[6/8] Compiling methods... [*******************] (385.2s @ 3.02GB)
[7/8] Layouting methods... [****] (14.0s @ 2.00GB)
[8/8] Creating image... [*****] (30.7s @ 2.72GB)
48.81MB (58.93%) for code area: 48,318 compilation units
30.92MB (37.33%) for image heap: 398,288 objects and 175 resources
3.10MB ( 3.75%) for other data
82.83MB in total

// Omitted for clarity

Finished generating 'springboot-graalvm-docker' in 13m 7s.

// Omitted for clarity

在上述編譯輸出中,以下是一些關鍵要點:

  • 編譯過程使用 GraalVM Java 編譯器編譯應用程序
  • 編譯器會對類型、字段和方法進行可達性檢查
  • 然後,它會構建原生可執行文件並顯示可執行文件大小和編譯時間

編譯成功後,可以在目標目錄下找到原生可執行文件,該可執行文件可以在命令行中執行。

5. 構建 Docker 鏡像

本節將為先前步驟生成的原生可執行文件構建 Docker 鏡像。

讓我們創建以下 Dockerfile:

FROM ubuntu:jammy
COPY target/springboot-graalvm-docker /springboot-graalvm-docker
CMD ["/springboot-graalvm-docker"]

接下來,讓我們使用以下命令構建 Docker 鏡像:

$docker build -t springboot-graalvm-docker .

構建成功後,我們可以注意到 springboot-graalvm-docker Docker 鏡像可用:

$docker images | grep springboot-graalvm-docker

我們可以使用以下命令執行此圖像:

$docker run -p 8080:8080 springboot-graalvm-docker

上述命令啓動容器,我們可以注意到 Spring Boot 的啓動日誌:

// Ommited for clarity
***  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 14 ms
***  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
***  INFO 1 --- [           main] c.b.g.GraalvmDockerImageApplication      : Started GraalvmDockerImageApplication in 0.043 seconds (process running for 0.046)

應用程序啓動時間為 43 毫秒。可以通過以下命令訪問 REST 端點:

$curl localhost:8080

它顯示了以下輸出:

Hello GraalVM

6. 結論

在本文中,我們為 GraalVM 原生可執行文件構建了一個 Docker 鏡像。

我們討論了 GraalVM 原生鏡像及其優勢。它對於需要快速啓動和低內存佔用率的應用場景非常有用。接下來,我們使用 GraalVM 原生鏡像編譯器生成了 Spring Boot 應用程序的原生可執行文件。最後,我們使用該原生可執行文件和 Docker 鏡像,開發了一個 Docker 鏡像並啓動了 Docker 容器。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.