新しくリリースされた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_IMAGE
をtrue
に設定します
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
次のようにビルドが開始されます。
ビルドには時間がかかります。マシンスペックにもよりますが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へのプッシュも簡単に行うことができます。