--- title: Cloud Native BuildpacksでGraalVMを使ったSpring Bootのnative imageのDocker image作成する tags: ["Cloud Native Buildpacks", "Spring Boot", "GraalVM", "Docker"] categories: ["Dev", "Infrastructure", "CloudNativeBuildpacks", "SpringBoot", "GraalVM"] date: 2020-09-07T12:16:34Z updated: 2020-09-21T04:26:30Z --- [前記事](/entries/542)ではCustom Builderを使ってnative imageのDocker Imageを作成する方法を紹介しましたが、Paketo Buildpackで正式にGraalVM buildpackが同梱されたため、改めて紹介します。 Spring BootアプリをGraalVMでnative image化するプロジェクト[Spring GraalVM Native Feature](https://github.com/spring-projects-experimental/spring-graalvm-native)の開発が進んでいますが、 [`java-native-image`](https://github.com/paketo-buildpacks/java-native-image) Buildpackを使えば、 Spring BootのアプリをGraalVM+spring-graalvm-nativeを使ってnative image化できます。 GraalVMもspring-graalvm-nativeもインストール不要で、普通のソースコードからビルド可能です。 Paketo Buildpacks標準の[`java`](https://github.com/paketo-buildpacks/java) buildpackがJREとして[`bellsoft-liberica`](https://github.com/paketo-buildpacks/bellsoft-liberica) buildpackを内包しているのに対して、 `java-native-image` buildpackは、[`graalvm`](https://github.com/paketo-buildpacks/graalvm) buildpackを内包しています。 Paketo Buildpacksの * `paketobuildpacks/builder:base` builderには`java`と`java-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`](https://buildpacks.io/docs/install-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を使う例を紹介します。使い方は[ドキュメント](https://repo.spring.io/milestone/org/springframework/experimental/spring-graalvm-native-docs/0.8.0/spring-graalvm-native-docs-0.8.0.zip!/reference/index.html#_configure_the_maven_plugin)に記載されています。 `pom.xml`に以下の箇所を追加します。 ```xml org.springframework.boot spring-boot-maven-plugin paketobuildpacks/builder:tiny 1 -Dspring.native.remove-yaml-support=true -Dspring.spel.ignore=true -Dspring.xml.ignore=true -Dspring.spel.ignore=true ``` もしくは次の`sed`コマンドで編集します。 ``` sed -i '' -e 's|spring-boot-maven-plugin|spring-boot-maven-pluginpaketobuildpacks/builder:tiny1-Dspring.native.remove-yaml-support=true -Dspring.spel.ignore=true -Dspring.xml.ignore=true -Dspring.spel.ignore=true|' 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に含まれる予定です。