前記事ではCustom Builderを使ってnative imageのDocker Imageを作成する方法を紹介しましたが、Paketo Buildpackで正式にGraalVM buildpackが同梱されたため、改めて紹介します。
Spring BootアプリをGraalVMでnative image化するプロジェクトSpring GraalVM Native Featureの開発が進んでいますが、java-native-image Buildpackを使えば、
Spring BootのアプリをGraalVM+spring-graalvm-nativeを使ってnative image化できます。
GraalVMもspring-graalvm-nativeもインストール不要で、普通のソースコードからビルド可能です。
Paketo Buildpacks標準のjava buildpackがJREとしてbellsoft-liberica buildpackを内包しているのに対して、java-native-image buildpackは、graalvm buildpackを内包しています。
Paketo Buildpacksの
paketobuildpacks/builder:basebuilderにはjavaとjava-native-image両方のbuildpackを含んでいます。ビルド時に環境変数BP_BOOT_NATIVE_IMAGEが設定されていればjava-native-imageが使用されます。paketobuildpacks/builder:tinybuilderにはjava-native-imageが含まれています。tinyのベースイメージは最小構成のUbuntuイメージであり、実行可能なnative imageを実行する環境として最適化されています。
pack inspect-builderでそれぞれのBuilderにjava-native-imageが含まれていることを確認します。
$ pack inspect-builder paketobuildpacks/builder:base
Inspecting builder: paketobuildpacks/builder:base
REMOTE:
Description: Ubuntu bionic base image with buildpacks for Java, NodeJS and Golang
Created By:
Name: Pack CLI
Version: 0.13.1+git-4134cc6.build-1135
Trusted: Yes
Stack:
ID: io.buildpacks.stacks.bionic
Lifecycle:
Version: 0.9.1
Buildpack APIs:
Deprecated: (none)
Supported: 0.2, 0.3, 0.4
Platform APIs:
Deprecated: (none)
Supported: 0.3, 0.4
Run Images:
index.docker.io/paketobuildpacks/run:base-cnb
gcr.io/paketo-buildpacks/run:base-cnb
Buildpacks:
...
Detection Order:
├ Group #1:
│ └ paketo-buildpacks/java-native-image@3.2.0
│ └ Group #1:
│ ├ paketo-buildpacks/graalvm@3.2.1
│ ├ paketo-buildpacks/gradle@3.1.0 (optional)
│ ├ paketo-buildpacks/leiningen@1.1.0 (optional)
│ ├ paketo-buildpacks/maven@3.1.0 (optional)
│ ├ paketo-buildpacks/sbt@3.1.0 (optional)
│ ├ paketo-buildpacks/executable-jar@3.1.0 (optional)
│ ├ paketo-buildpacks/spring-boot@3.2.0 (optional)
│ ├ paketo-buildpacks/spring-boot-native-image@1.3.0
│ ├ paketo-buildpacks/procfile@2.0.2 (optional)
│ ├ paketo-buildpacks/environment-variables@2.1.0 (optional)
│ └ paketo-buildpacks/image-labels@2.0.3 (optional)
├ Group #2:
│ └ paketo-buildpacks/java@3.0.2
...
$ pack inspect-builder paketobuildpacks/builder:tiny
Inspecting builder: paketobuildpacks/builder:tiny
REMOTE:
Description: Tiny base image (bionic build image, distroless run image) with buildpacks for Golang
Created By:
Name: Pack CLI
Version: 0.13.1+git-4134cc6.build-1135
Trusted: Yes
Stack:
ID: io.paketo.stacks.tiny
Lifecycle:
Version: 0.9.1
Buildpack APIs:
Deprecated: (none)
Supported: 0.2, 0.3, 0.4
Platform APIs:
Deprecated: (none)
Supported: 0.3, 0.4
Run Images:
index.docker.io/paketobuildpacks/run:tiny-cnb
gcr.io/paketo-buildpacks/run:tiny-cnb
Buildpacks:
ID VERSION HOMEPAGE
...
Detection Order:
├ Group #1:
│ └ paketo-buildpacks/java-native-image@3.2.0
│ └ Group #1:
│ ├ paketo-buildpacks/graalvm@3.2.1
│ ├ paketo-buildpacks/gradle@3.1.0 (optional)
│ ├ paketo-buildpacks/leiningen@1.1.0 (optional)
│ ├ paketo-buildpacks/maven@3.1.0 (optional)
│ ├ paketo-buildpacks/sbt@3.1.0 (optional)
│ ├ paketo-buildpacks/executable-jar@3.1.0 (optional)
│ ├ paketo-buildpacks/spring-boot@3.2.0 (optional)
│ ├ paketo-buildpacks/spring-boot-native-image@1.3.0
│ ├ paketo-buildpacks/procfile@2.0.2 (optional)
│ ├ paketo-buildpacks/environment-variables@2.1.0 (optional)
│ └ paketo-buildpacks/image-labels@2.0.3 (optional)
└ Group #2:
└ paketo-buildpacks/go@0.1.0
...
最適なpaketobuildpacks/builder:tinyを使って実際にSpring Bootアプリのnative imageを作成します。
まずはソースコードを用意します。執筆段階ではspring-graalvm-native 0.8.0が使われ、Spring Boot 2.4が必要です。ここでは2.4.0-M2を使用します。
curl https://start.spring.io/starter.tgz \
-s \
-d javaVersion=11 \
-d artifactId=hello \
-d bootVersion=2.4.0-M2 \
-d baseDir=hello \
-d dependencies=webflux,actuator \
-d packageName=com.example \
-d applicationName=HelloApplication | tar -xzvf -
sed -i '' 's/@SpringBootApplication/@SpringBootApplication(proxyBeanMethods = false)/' hello/src/main/java/com/example/HelloApplication.java
cd hello
./mvnw clean package -Dmaven.test.skip=true
イメージを作成するには
があります。
pack CLIを使う方法
pack 0.13.1で動作確認しています。
pack build hello \
--builder paketobuildpacks/builder:tiny \
--path target/hello*.jar \
-e BP_BOOT_NATIVE_IMAGE=1 \
-e BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS="-Dspring.native.remove-yaml-support=true -Dspring.spel.ignore=true -Dspring.xml.ignore=true -Dspring.spel.ignore=true"
次のようなログが出力されます。(キャッシュがない場合はGraalVM JDKのダウンロードに時間がかかります...)
Status: Downloaded newer image for paketobuildpacks/run:tiny-cnb
===> DETECTING
4 of 11 buildpacks participating
paketo-buildpacks/graalvm 3.2.1
paketo-buildpacks/executable-jar 3.1.0
paketo-buildpacks/spring-boot 3.2.0
paketo-buildpacks/spring-boot-native-image 1.3.0
===> ANALYZING
Previous image with name "index.docker.io/library/hello:latest" not found
===> RESTORING
===> BUILDING
Paketo GraalVM Buildpack 3.2.1
https://github.com/paketo-buildpacks/graalvm
Build Configuration:
$BP_JVM_VERSION 11.* the Java version
Launch Configuration:
$BPL_JVM_HEAD_ROOM 0 the headroom in memory calculation
$BPL_JVM_LOADED_CLASS_COUNT 35% of classes the number of loaded classes in memory calculation
$BPL_JVM_THREAD_COUNT 250 the number of threads in memory calculation
$JAVA_TOOL_OPTIONS the JVM launch flags
GraalVM JDK 11.0.8: Contributing to layer
Downloading from https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-20.2.0/graalvm-ce-java11-linux-amd64-20.2.0.tar.gz
Verifying checksum
Expanding to /layers/paketo-buildpacks_graalvm/jdk
Adding 127 container CA certificates to JVM truststore
GraalVM Native Image Substrate VM 11.0.8
Downloading from https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-20.2.0/native-image-installable-svm-java11-linux-amd64-20.2.0.jar
Verifying checksum
Installing substrate VM
Processing Component archive: /tmp/92b429939f12434575e4d586f79c5b686d322f29211d1608ed6055a97a35925c/native-image-installable-svm-java11-linux-amd64-20.2.0.jar
Installing new component: Native Image (org.graalvm.native-image, version 20.2.0)
Writing env.build/JAVA_HOME.override
Writing env.build/JDK_HOME.override
Paketo Spring Boot Buildpack 3.2.0
https://github.com/paketo-buildpacks/spring-boot
Image labels:
org.opencontainers.image.title
org.opencontainers.image.version
org.springframework.boot.spring-configuration-metadata.json
org.springframework.boot.version
Paketo Spring Boot Native Image Buildpack 1.3.0
https://github.com/paketo-buildpacks/spring-boot-native-image
Build Configuration:
$BP_BOOT_NATIVE_IMAGE 1 the build to create a native image (requires GraalVM)
$BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS -Dspring.native.remove-yaml-support=true -Dspring.spel.ignore=true the arguments to pass to the native-image command
Native Image: Contributing to layer
Spring GraalVM Native Feature 0.8.0
Downloading from https://repo.spring.io/milestone/org/springframework/experimental/spring-graalvm-native/0.8.0/spring-graalvm-native-0.8.0.jar
Verifying checksum
Executing native-image -Dspring.native.remove-yaml-support=true -Dspring.spel.ignore=true -H:+StaticExecutableWithDynamicLibC -H:Name=/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication -cp /workspace:/workspace/BOOT-INF/classes:/workspace/BOOT-INF/lib/spring-boot-starter-actuator-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-starter-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-context-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-aop-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-expression-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-autoconfigure-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-starter-logging-2.4.0-M2.jar:/workspace/BOOT-INF/lib/logback-classic-1.2.3.jar:/workspace/BOOT-INF/lib/logback-core-1.2.3.jar:/workspace/BOOT-INF/lib/log4j-to-slf4j-2.13.3.jar:/workspace/BOOT-INF/lib/log4j-api-2.13.3.jar:/workspace/BOOT-INF/lib/jul-to-slf4j-1.7.30.jar:/workspace/BOOT-INF/lib/jakarta.annotation-api-1.3.5.jar:/workspace/BOOT-INF/lib/snakeyaml-1.26.jar:/workspace/BOOT-INF/lib/spring-boot-actuator-autoconfigure-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-actuator-2.4.0-M2.jar:/workspace/BOOT-INF/lib/jackson-databind-2.11.2.jar:/workspace/BOOT-INF/lib/jackson-annotations-2.11.2.jar:/workspace/BOOT-INF/lib/jackson-core-2.11.2.jar:/workspace/BOOT-INF/lib/jackson-datatype-jsr310-2.11.2.jar:/workspace/BOOT-INF/lib/micrometer-core-1.5.4.jar:/workspace/BOOT-INF/lib/HdrHistogram-2.1.12.jar:/workspace/BOOT-INF/lib/LatencyUtils-2.0.3.jar:/workspace/BOOT-INF/lib/spring-boot-starter-webflux-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-starter-json-2.4.0-M2.jar:/workspace/BOOT-INF/lib/jackson-datatype-jdk8-2.11.2.jar:/workspace/BOOT-INF/lib/jackson-module-parameter-names-2.11.2.jar:/workspace/BOOT-INF/lib/spring-boot-starter-reactor-netty-2.4.0-M2.jar:/workspace/BOOT-INF/lib/reactor-netty-http-1.0.0-M2.jar:/workspace/BOOT-INF/lib/netty-codec-http-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-common-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-buffer-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-transport-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-codec-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-handler-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-codec-http2-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-resolver-dns-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-resolver-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-codec-dns-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-transport-native-epoll-4.1.51.Final-linux-x86_64.jar:/workspace/BOOT-INF/lib/netty-transport-native-unix-common-4.1.51.Final.jar:/workspace/BOOT-INF/lib/reactor-netty-core-1.0.0-M2.jar:/workspace/BOOT-INF/lib/netty-handler-proxy-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-codec-socks-4.1.51.Final.jar:/workspace/BOOT-INF/lib/spring-web-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-beans-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-webflux-5.3.0-M2.jar:/workspace/BOOT-INF/lib/nio-multipart-parser-1.1.0.jar:/workspace/BOOT-INF/lib/slf4j-api-1.7.30.jar:/workspace/BOOT-INF/lib/nio-stream-storage-1.1.3.jar:/workspace/BOOT-INF/lib/spring-core-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-jcl-5.3.0-M2.jar:/workspace/BOOT-INF/lib/reactor-core-3.4.0-M2.jar:/workspace/BOOT-INF/lib/reactive-streams-1.0.3.jar:/workspace/BOOT-INF/lib/spring-boot-jarmode-layertools-2.4.0-M2.jar:/tmp/0c24ece155eaac02cb106cced886ff70f83a02e13e63102f8242bd0d6b4ad5e2/spring-graalvm-native-0.8.0.jar com.example.HelloApplication
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] classlist: 9,279.94 ms, 0.94 GB
____ _ _____ ___ ____ ___
/ __/__ ____(_)__ ___ _ / ___/______ ____ _/ / | / / |/ /
_\ \/ _ \/ __/ / _ \/ _ `/ / (_ / __/ _ `/ _ `/ /| |/ / /|_/ /
/___/ .__/_/ /_/_//_/\_, / \___/_/ \_,_/\_,_/_/ |___/_/ /_/
/_/__ __ _ /___/
/ |/ /__ _/ /_(_) _____
/ / _ `/ __/ / |/ / -_)
/_/|_/\_,_/\__/_/|___/\__/
Removing unused configurations
Removing Yaml support
Removing XML support
Removing SpEL support
Removing JMX support
Use -Dspring.native.verbose=true on native-image call to see more detailed information from the feature
FM: mode not set, searching for resources...
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] (cap): 709.91 ms, 0.94 GB
Inferred feature operating mode: reflection
...
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] (clinit): 1,360.84 ms, 4.57 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] (typeflow): 18,306.40 ms, 4.57 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] (objects): 30,113.05 ms, 4.57 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] (features): 5,324.77 ms, 4.57 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] analysis: 57,663.14 ms, 4.57 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] universe: 2,615.67 ms, 4.57 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] (parse): 4,350.10 ms, 4.57 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] (inline): 6,812.34 ms, 6.07 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] (compile): 27,659.86 ms, 5.96 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] compile: 42,023.21 ms, 5.96 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] image: 5,763.00 ms, 6.00 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] write: 952.44 ms, 6.00 GB
[/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:143] [total]: 122,393.35 ms, 6.00 GB
Removing bytecode
Process types:
native-image: /workspace/com.example.HelloApplication (direct)
task: /workspace/com.example.HelloApplication (direct)
web: /workspace/com.example.HelloApplication (direct)
===> EXPORTING
Adding 1/1 app layer(s)
Adding layer 'launcher'
Adding layer 'config'
Adding layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Adding label 'org.opencontainers.image.title'
Adding label 'org.opencontainers.image.version'
Adding label 'org.springframework.boot.spring-configuration-metadata.json'
Adding label 'org.springframework.boot.version'
Setting default process type 'web'
*** Images (fa9ef50ccd5d):
index.docker.io/library/hello:latest
Adding cache layer 'paketo-buildpacks/graalvm:jdk'
Adding cache layer 'paketo-buildpacks/spring-boot-native-image:native-image'
Successfully built image hello
作られたDocker Imageのサイズは約80MBです。
$ docker images | grep hello
hello latest fa9ef50ccd5d 40 years ago 86.4MB
Spring Boot Maven/Gradle Pluginを使う方法
Maven Pluginを使う例を紹介します。使い方はドキュメントに記載されています。pom.xmlに以下の箇所を追加します。
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!-- from -->
<configuration>
<image>
<builder>paketobuildpacks/builder:tiny</builder>
<env>
<BP_BOOT_NATIVE_IMAGE>1</BP_BOOT_NATIVE_IMAGE>
<BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
-Dspring.native.remove-yaml-support=true
-Dspring.spel.ignore=true
-Dspring.xml.ignore=true
-Dspring.spel.ignore=true
</BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
</env>
</image>
</configuration>
<!-- to -->
</plugin>
</plugins>
</build>
もしくは次のsedコマンドで編集します。
sed -i '' -e 's|<artifactId>spring-boot-maven-plugin</artifactId>|<artifactId>spring-boot-maven-plugin</artifactId><configuration><image><builder>paketobuildpacks/builder:tiny</builder><env><BP_BOOT_NATIVE_IMAGE>1</BP_BOOT_NATIVE_IMAGE><BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>-Dspring.native.remove-yaml-support=true -Dspring.spel.ignore=true -Dspring.xml.ignore=true -Dspring.spel.ignore=true</BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS></env></image></configuration>|' pom.xml
./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=hello
次のようなログが出力されます。(キャッシュがない場合はGraalVM JDKのダウンロードに時間がかかります...)
[INFO] --- spring-boot-maven-plugin:2.4.0-M2:build-image (default-cli) @ hello ---
[INFO] Building image 'docker.io/library/hello:latest'
[INFO]
[INFO] > Pulling builder image 'docker.io/paketobuildpacks/builder:tiny' 100%
[INFO] > Pulled builder image 'paketobuildpacks/builder@sha256:2696f31b84d61be196596e44d50480997e6a3a759eaa9b7de8d5ef06154f7b0b'
[INFO] > Pulling run image 'docker.io/paketobuildpacks/run:tiny-cnb' 100%
[INFO] > Pulled run image 'paketobuildpacks/run@sha256:34b01fd9a3745fcaa345f8993938291c931f7977cc2bee78ed377da2edc55e3d'
[INFO] > Executing lifecycle version v0.9.1
[INFO] > Using build cache volume 'pack-cache-ae2811f8f959.build'
[INFO]
[INFO] > Running creator
[INFO] [creator] ===> DETECTING
[INFO] [creator] 4 of 11 buildpacks participating
[INFO] [creator] paketo-buildpacks/graalvm 3.2.1
[INFO] [creator] paketo-buildpacks/executable-jar 3.1.0
[INFO] [creator] paketo-buildpacks/spring-boot 3.2.0
[INFO] [creator] paketo-buildpacks/spring-boot-native-image 1.3.0
[INFO] [creator] ===> ANALYZING
[INFO] [creator] Previous image with name "docker.io/library/hello:latest" not found
[INFO] [creator] Restoring metadata for "paketo-buildpacks/graalvm:jdk" from cache
[INFO] [creator] Restoring metadata for "paketo-buildpacks/spring-boot-native-image:native-image" from cache
[INFO] [creator] ===> RESTORING
[INFO] [creator] Restoring data for "paketo-buildpacks/graalvm:jdk" from cache
[INFO] [creator] Restoring data for "paketo-buildpacks/spring-boot-native-image:native-image" from cache
[INFO] [creator] ===> BUILDING
[INFO] [creator]
[INFO] [creator] Paketo GraalVM Buildpack 3.2.1
[INFO] [creator] https://github.com/paketo-buildpacks/graalvm
[INFO] [creator] Build Configuration:
[INFO] [creator] $BP_JVM_VERSION 11.* the Java version
[INFO] [creator] Launch Configuration:
[INFO] [creator] $BPL_JVM_HEAD_ROOM 0 the headroom in memory calculation
[INFO] [creator] $BPL_JVM_LOADED_CLASS_COUNT 35% of classes the number of loaded classes in memory calculation
[INFO] [creator] $BPL_JVM_THREAD_COUNT 250 the number of threads in memory calculation
[INFO] [creator] $JAVA_TOOL_OPTIONS the JVM launch flags
[INFO] [creator] GraalVM JDK 11.0.8: Reusing cached layer
[INFO] [creator]
[INFO] [creator] Paketo Spring Boot Buildpack 3.2.0
[INFO] [creator] https://github.com/paketo-buildpacks/spring-boot
[INFO] [creator] Image labels:
[INFO] [creator] org.opencontainers.image.title
[INFO] [creator] org.opencontainers.image.version
[INFO] [creator] org.springframework.boot.spring-configuration-metadata.json
[INFO] [creator] org.springframework.boot.version
[INFO] [creator]
[INFO] [creator] Paketo Spring Boot Native Image Buildpack 1.3.0
[INFO] [creator] https://github.com/paketo-buildpacks/spring-boot-native-image
[INFO] [creator] Build Configuration:
[INFO] [creator] $BP_BOOT_NATIVE_IMAGE 1 the build to create a native image (requires GraalVM)
[INFO] [creator] $BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS -Dspring.native.remove-yaml-support=true -Dspring.spel.ignore=true the arguments to pass to the native-image command
[INFO] [creator] Native Image: Contributing to layer
[INFO] [creator] Spring GraalVM Native Feature 0.8.0
[INFO] [creator] Downloading from https://repo.spring.io/milestone/org/springframework/experimental/spring-graalvm-native/0.8.0/spring-graalvm-native-0.8.0.jar
[INFO] [creator] Verifying checksum
[INFO] [creator] Executing native-image -Dspring.native.remove-yaml-support=true -Dspring.spel.ignore=true -H:+StaticExecutableWithDynamicLibC -H:Name=/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication -cp /workspace:/workspace/BOOT-INF/classes:/workspace/BOOT-INF/lib/spring-boot-starter-actuator-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-starter-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-context-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-aop-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-expression-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-autoconfigure-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-starter-logging-2.4.0-M2.jar:/workspace/BOOT-INF/lib/logback-classic-1.2.3.jar:/workspace/BOOT-INF/lib/logback-core-1.2.3.jar:/workspace/BOOT-INF/lib/log4j-to-slf4j-2.13.3.jar:/workspace/BOOT-INF/lib/log4j-api-2.13.3.jar:/workspace/BOOT-INF/lib/jul-to-slf4j-1.7.30.jar:/workspace/BOOT-INF/lib/jakarta.annotation-api-1.3.5.jar:/workspace/BOOT-INF/lib/snakeyaml-1.26.jar:/workspace/BOOT-INF/lib/spring-boot-actuator-autoconfigure-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-actuator-2.4.0-M2.jar:/workspace/BOOT-INF/lib/jackson-databind-2.11.2.jar:/workspace/BOOT-INF/lib/jackson-annotations-2.11.2.jar:/workspace/BOOT-INF/lib/jackson-core-2.11.2.jar:/workspace/BOOT-INF/lib/jackson-datatype-jsr310-2.11.2.jar:/workspace/BOOT-INF/lib/micrometer-core-1.5.4.jar:/workspace/BOOT-INF/lib/HdrHistogram-2.1.12.jar:/workspace/BOOT-INF/lib/LatencyUtils-2.0.3.jar:/workspace/BOOT-INF/lib/spring-boot-starter-webflux-2.4.0-M2.jar:/workspace/BOOT-INF/lib/spring-boot-starter-json-2.4.0-M2.jar:/workspace/BOOT-INF/lib/jackson-datatype-jdk8-2.11.2.jar:/workspace/BOOT-INF/lib/jackson-module-parameter-names-2.11.2.jar:/workspace/BOOT-INF/lib/spring-boot-starter-reactor-netty-2.4.0-M2.jar:/workspace/BOOT-INF/lib/reactor-netty-http-1.0.0-M2.jar:/workspace/BOOT-INF/lib/netty-codec-http-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-common-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-buffer-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-transport-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-codec-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-handler-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-codec-http2-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-resolver-dns-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-resolver-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-codec-dns-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-transport-native-epoll-4.1.51.Final-linux-x86_64.jar:/workspace/BOOT-INF/lib/netty-transport-native-unix-common-4.1.51.Final.jar:/workspace/BOOT-INF/lib/reactor-netty-core-1.0.0-M2.jar:/workspace/BOOT-INF/lib/netty-handler-proxy-4.1.51.Final.jar:/workspace/BOOT-INF/lib/netty-codec-socks-4.1.51.Final.jar:/workspace/BOOT-INF/lib/spring-web-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-beans-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-webflux-5.3.0-M2.jar:/workspace/BOOT-INF/lib/nio-multipart-parser-1.1.0.jar:/workspace/BOOT-INF/lib/slf4j-api-1.7.30.jar:/workspace/BOOT-INF/lib/nio-stream-storage-1.1.3.jar:/workspace/BOOT-INF/lib/spring-core-5.3.0-M2.jar:/workspace/BOOT-INF/lib/spring-jcl-5.3.0-M2.jar:/workspace/BOOT-INF/lib/reactor-core-3.4.0-M2.jar:/workspace/BOOT-INF/lib/reactive-streams-1.0.3.jar:/workspace/BOOT-INF/lib/spring-boot-jarmode-layertools-2.4.0-M2.jar:/tmp/0c24ece155eaac02cb106cced886ff70f83a02e13e63102f8242bd0d6b4ad5e2/spring-graalvm-native-0.8.0.jar com.example.HelloApplication
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] classlist: 8,953.19 ms, 0.94 GB
[INFO] [creator] ____ _ _____ ___ ____ ___
[INFO] [creator] / __/__ ____(_)__ ___ _ / ___/______ ____ _/ / | / / |/ /
[INFO] [creator] _\ \/ _ \/ __/ / _ \/ _ `/ / (_ / __/ _ `/ _ `/ /| |/ / /|_/ /
[INFO] [creator] /___/ .__/_/ /_/_//_/\_, / \___/_/ \_,_/\_,_/_/ |___/_/ /_/
[INFO] [creator] /_/__ __ _ /___/
[INFO] [creator] / |/ /__ _/ /_(_) _____
[INFO] [creator] / / _ `/ __/ / |/ / -_)
[INFO] [creator] /_/|_/\_,_/\__/_/|___/\__/
[INFO] [creator]
[INFO] [creator] Removing unused configurations
[INFO] [creator] Removing Yaml support
[INFO] [creator] Removing XML support
[INFO] [creator] Removing SpEL support
[INFO] [creator] Removing JMX support
[INFO] [creator] Use -Dspring.native.verbose=true on native-image call to see more detailed information from the feature
[INFO] [creator] FM: mode not set, searching for resources...
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] (cap): 730.72 ms, 0.94 GB
[INFO] [creator] Inferred feature operating mode: reflection
...
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] (clinit): 1,198.72 ms, 3.73 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] (typeflow): 17,680.04 ms, 3.73 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] (objects): 30,556.66 ms, 3.73 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] (features): 5,516.40 ms, 3.73 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] analysis: 57,555.65 ms, 3.73 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] universe: 2,029.73 ms, 3.73 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] (parse): 4,760.77 ms, 3.90 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] (inline): 6,137.95 ms, 5.50 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] (compile): 23,873.16 ms, 6.03 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] compile: 37,802.77 ms, 6.03 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] image: 6,487.10 ms, 6.03 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] write: 962.03 ms, 6.03 GB
[INFO] [creator] [/layers/paketo-buildpacks_spring-boot-native-image/native-image/com.example.HelloApplication:145] [total]: 118,138.94 ms, 6.03 GB
[INFO] [creator] Removing bytecode
[INFO] [creator] Process types:
[INFO] [creator] native-image: /workspace/com.example.HelloApplication (direct)
[INFO] [creator] task: /workspace/com.example.HelloApplication (direct)
[INFO] [creator] web: /workspace/com.example.HelloApplication (direct)
[INFO] [creator] ===> EXPORTING
[INFO] [creator] Adding 1/1 app layer(s)
[INFO] [creator] Adding layer 'launcher'
[INFO] [creator] Adding layer 'config'
[INFO] [creator] Adding label 'io.buildpacks.lifecycle.metadata'
[INFO] [creator] Adding label 'io.buildpacks.build.metadata'
[INFO] [creator] Adding label 'io.buildpacks.project.metadata'
[INFO] [creator] Adding label 'org.opencontainers.image.title'
[INFO] [creator] Adding label 'org.opencontainers.image.version'
[INFO] [creator] Adding label 'org.springframework.boot.spring-configuration-metadata.json'
[INFO] [creator] Adding label 'org.springframework.boot.version'
[INFO] [creator] *** Images (773c139a2db6):
[INFO] [creator] docker.io/library/hello:latest
[INFO] [creator] Reusing cache layer 'paketo-buildpacks/graalvm:jdk'
[INFO] [creator] Adding cache layer 'paketo-buildpacks/spring-boot-native-image:native-image'
[INFO]
[INFO] Successfully built image 'docker.io/library/hello:latest'
ビルドしたイメージを実行します。
docker run --rm \
-p 8080:8080 \
-e MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE=info,health,env \
hello
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::
2020-09-07 12:15:02.839 INFO 1 --- [ main] com.example.HelloApplication : Starting HelloApplication using Java 11.0.8 on c91a0a1816f4 with PID 1 (/workspace/com.example.HelloApplication started by cnb in /workspace)
2020-09-07 12:15:02.840 INFO 1 --- [ main] com.example.HelloApplication : No active profile set, falling back to default profiles: default
2020-09-07 12:15:02.905 INFO 1 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 3 endpoint(s) beneath base path '/actuator'
2020-09-07 12:15:02.911 WARN 1 --- [ main] i.m.c.i.binder.jvm.JvmGcMetrics : GC notifications will not be available because MemoryPoolMXBeans are not provided by the JVM
2020-09-07 12:15:02.919 WARN 1 --- [ main] io.netty.channel.DefaultChannelId : Failed to find the current process ID from ''; using a random value: 299229231
2020-09-07 12:15:02.921 INFO 1 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2020-09-07 12:15:02.922 INFO 1 --- [ main] com.example.HelloApplication : Started HelloApplication in 0.093 seconds (JVM running for 0.096)
非常に高速(0.093秒)に起動します。
$ curl -s http://localhost:8080/actuator/env | jq '.propertySources[2].properties["java.vm.name"]'
{
"value": "Substrate VM"
}
$ curl -s http://localhost:8080/actuator/env | jq '.propertySources[2].properties["java.vm.version"]'
{
"value": "GraalVM 20.2.0 Java 11"
}
Substrate VMで動いていることがわかります。
非常に簡単にnative imageのdocker imageを作成できました。
Spring GraalVM Native Featureは今後も改善されていき、native image化できるアプリケーションの種類が増えていく予定です。
最終的にはSprig Boot 3.0に含まれる予定です。