warning
この記事は2年以上前に更新されたものです。情報が古くなっている可能性があります。

前記事では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:base builderにはjavajava-native-image両方のbuildpackを含んでいます。ビルド時に環境変数BP_BOOT_NATIVE_IMAGEが設定されていればjava-native-imageが使用されます。
  • paketobuildpacks/builder:tiny builderには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に含まれる予定です。

Found a mistake? Update the entry.
Share this article: