Spring Boot 3でのGraalVMネイティブイメージの生成方法

新しくリリースされたSpring Boot 3ではGraalVMネイティブイメージの生成がサポートされました。この記事ではSpring BootでGraalVMネイティブイメージを作成する方法を紹介します。

GraalVMとは

GraalVMはOracleが開発しているJava仮想マシンです。Java仮想マシンとしての機能に加えて、Java、Scala、Kotlin、Groovy、JavaScript、Ruby、Python、R、C、C++、WebAssemblyなどの言語を実行できます。また、GraalVMはJavaアプリケーションをネイティブイメージに変換することができます。

今回そのGraalVMネイティブイメージをSpring Bootで作成する方法を紹介します。

構築環境

今回は次の環境で検証を行いました

  • Ubuntu 22.04
  • Java 17

Spring Bootプロジェクト作成

次のcurlコマンドでSpring Bootプロジェクトをダウンロードします。VSCodeのターミナルを開いて次のコマンドを実行してください。

コマンド実行

curl -s https://start.spring.io/starter.zip \
  -d bootVersion=3.2.0 \
  -d language=java \
  -d javaVersion=17 \
  -d type=gradle-project \
  -d groupId=com.example \
  -d artifactId=demo \
  -d name=demo \
  -d dependencies=web,devtools,lombok,actuator \
  -o demo.zip && unzip demo.zip -d demo && rm demo.zip

依存関係の追加

build.gradleを編集します。GraalVMネイティブイメージを作成するために必要な依存関係を追加します。

  • plugins
    • org.graalvm.buildtools.native
      • GraalVMネイティブイメージを作成するためのGradleプラグイン
  • bootBuildImageタスクの設定
    • builder
      • ビルドに使用するDockerイメージを指定します
      • 今回はpaketobuildpacks/builder:tinyを指定します
      • tinyはメモリ使用量を削減するためのDockerイメージです
    • environment
      • GraalVMネイティブイメージを作成するために必要な環境変数を指定します
      • 今回はBP_NATIVE_IMAGEtrueに設定します

build.gradle

plugins {
  id 'java'
  id 'org.springframework.boot' version '3.1.3'
  id 'io.spring.dependency-management' version '1.1.0'
id 'org.graalvm.buildtools.native' version '0.9.28'
} group = 'com.example' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() }
tasks.named('bootBuildImage') { builder = 'paketobuildpacks/builder:tiny' environment = ['BP_NATIVE_IMAGE': 'true'] }

アプリケーションの実装

次にSpring Bootアプリケーションの実装を行います。今回は簡単なHello WorldをREST APIとして返すだけのアプリケーションを作成します。src/main/java/com/example/demo/DemoApplication.javaを次のように編集します。

com.example.demo.DemoApplication.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController
@SpringBootApplication public class DemoApplication {
@RequestMapping("/") public String home() { return "Hello World!"; }
public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }

ネイティブイメージの作成

それではこのSpring BootアプリケーションをGradleでビルドしてネイティブイメージを作成します。VSCodeのターミナルを開いて次のコマンドを実行してください。

コマンド実行

./gradlew bootBuildImage

次のようにビルドが開始されます。

NOTE

ビルドには時間がかかります。マシンスペックにもよりますが5分以上かかることもあります。

次のように「BUILD SUCCESSFUL」と表示されればビルドが完了です。

ビルドが完了するとDockerイメージが作成されます。docker imagesコマンドを実行してイメージが作成されていることを確認します。

コマンド実行結果

docker images

次のようにdemo:0.0.1-SNAPSHOTというイメージが作成されていることが確認できます。

コンテナの起動

ビルドされたコンテナイメージを使ってコンテナを起動します。次のコマンドを実行してください。

コマンド実行

docker run -d -p 8080:8080 demo:0.0.1-SNAPSHOT

動作確認

次のコマンドで動作確認を行います。

コマンド実行

curl http://localhost:8080

レスポンスが返ってくれば成功です。

コマンド実行結果

Hello World!

メトリクスの確認

次のコマンドでメトリクスを確認します。

コマンド実行

docker stats

このようにメモリ使用量が少ないことが確認できます。

Docker Hubへのプッシュ

生成したネイティブイメージをDocker Hubへプッシュするにはbuild.gradleを次のように編集する必要があります。

build.gradle

plugins {
  id 'java'
  id 'org.springframework.boot' version '3.1.3'
  id 'io.spring.dependency-management' version '1.1.0'
  id 'org.graalvm.buildtools.native' version '0.9.28'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
  sourceCompatibility = '17'
}

repositories {
  mavenCentral()
}

dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-actuator'
  implementation 'org.springframework.boot:spring-boot-starter-web'
  testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
  useJUnitPlatform()
}

tasks.named('bootBuildImage') {
  builder = 'paketobuildpacks/builder:tiny'
  environment = ['BP_NATIVE_IMAGE': 'true']
imageName = '<Docker Hubアカウント名>/<リポジトリ名>:${version}' publish = true docker { publishRegistry { url = 'https://index.docker.io/v1/' username = '<Docker Hubアカウント名>' password = '<Docker Hubアカウントのアクセストークン>' } }
}

上記のとおりbootBuildImageタスクの設定を追加します。以下の箇所は任意に変更してください。

  • <Docker Hubアカウント名>
    • ご自身のDocker Hubのアカウント名を指定してください
  • <リポジトリ名>
    • ご自身のDocker Hubのリポジトリ名を指定してください
  • <Docker Hubアカウントのアクセストークン>
    • ご自身のDocker Hubアカウントのアクセストークンを指定してください

プッシュ

次のコマンドでDocker Hubへプッシュします。

コマンド実行

./gradlew bootBuildImage

次のようにビルドが完了されるとDocker Hubへプッシュされます。

プッシュの確認

Docker Hubにログインしてプッシュしたイメージがあることを確認します。

まとめ

Spring Boot 3でGraalVMネイティブイメージの生成方法を紹介しました。GraalVMネイティブイメージを使うことでメモリ使用量を削減することができます。また、Docker Hubへのプッシュも簡単に行うことができます。

コメントを残す

マークダウン形式でコメントを入力できます。

アップロードファイルの最大サイズ: 512 MB。 画像, 音声, 動画, 文書, スプレッドシート, 対話型, テキスト, アーカイブ, コード, その他 をアップロードできます。 Youtube、Facebook、Twitter および他サービスへのリンクは自動的にコメント内に埋め込まれます。 ここにファイルをドロップ

プロフィール背景
Ryosuke
Ryosuke

ITエンジニア & 講師

クラウドネイティブやアーキテクチャ設計の講師として活動しながら、ITエンジニアのDXを推進するために新しい技術やベストプラクティスを常に学び、エンジニアの生産性と開発品質の向上に貢献することを目指しています。猫5匹飼っています。山奥のポツンと一軒家に住んでいて、事務所は海の近くです。