This topic tells you how to use the Tanzu Java Native Image Buildpack.
The Tanzu Java Native Image Buildpack allows users to create an image containing a GraalVM native image application.
The Java Native Buildpack is a composite buildpack and each step in a build is handled by one of its components. The following docs describe common build configurations. For a full set of configuration options and capabilities see the homepages of the component buildpacks.
All Java Native Image Buildpack examples will use the Paketo sample applications.
Examples assume that the root of this repository is the working directory:
git clone https://github.com/paketo-buildpacks/samples
cd samples
The pack CLI is used throughout the examples. pack
is just one of several Cloud Native Buildpack platforms than can execute builds with the Java Native Image Buildpacks. For example, Spring Boot developers may want to explore the Spring Boot Maven Plugin or Spring Boot Gradle Plugin.
Examples assume that either the Paketo Tiny or Paketo Base builder is the default builder:
pack config default-builder paketobuildpacks/builder:tiny
All java native image example images should return {"status":"UP"}
from the actuator health endpoint.
docker run --rm --tty --publish 8080:8080 samples/java-native
curl -s http://localhost:8080/actuator/health | jq .
For all native image builds, it is required that:
BP_NATIVE_IMAGE
: Set at build time. Since Spring Boot v3.1, if you build a Spring Boot Jar into a native image, it can automatically set this environment variable for you. For more information, see this Paketo blog post.For Spring Boot applications, it is required that:
The Java Native Image Buildpack supports the same build tools and configuration options as the Java Buildpack. The build must produce an executable jar.
After compiling and packaging, the buildpack will replace provided application source code with the exploded JAR and proceed as described in Building from an Executable Jar.
The following command creates an image from source with maven
.
pack build samples/java-native \
--env BP_MAVEN_ACTIVE_PROFILES=native \
--path java/native-image/java-native-image-sample
Create a workload.yaml
.
A typical workload.yaml
for building the Paketo Java Native app from the samples in the my-apps
namespace looks like this:
---
apiVersion: carto.run/v1alpha1
kind: Workload
metadata:
labels:
app.kubernetes.io/part-of: java-native-sample
apps.tanzu.vmware.com/has-tests: "true"
apps.tanzu.vmware.com/workload-type: web
name: java-native-sample
namespace: my-apps
spec:
env:
- name: MANAGEMENT_ENDPOINT_HEALTH_PROBES_ADD_ADDITIONAL_PATHS
value: "true"
- name: MANAGEMENT_ENDPOINT_HEALTH_SHOW_DETAILS
value: always
- name: MANAGEMENT_ENDPOINTS_WEB_BASE_PATH
value: "/actuator"
- name: MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE
value: "*"
- name: MANAGEMENT_HEALTH_PROBES_ENABLED
value: "true"
- name: MANAGEMENT_SERVER_PORT
value: "8080"
build:
env:
- name: BP_JVM_VERSION
value: 17
- name: BP_NATIVE_IMAGE
value: true
- name: BP_MAVEN_ACTIVE_PROFILES
value: "native"
source:
git:
ref:
branch: native-properties
url: https://github.com/paketo-buildpacks/samples
subPath: java/native-image/java-native-image-sample
Where metadata.name
is the application name the workload is a part of, and spec.source.git
points to the remote source code.
Trigger an image build by running:
tanzu apps workload apply --file workload.yaml
You're done! The resulting app container will serve your Java Native app.
The Tanzu Java Function Buildpack provides a Spring Boot application for executing functions.
This buildpack will participate if any of the following conditions are met:
BP_FUNCTION
is explicitly set.func.yaml
is detected.The buildpack will do the following if detection passed:
$CLASSPATH
func.yaml
to the launch layerfunc.yaml
.Environment Variable | Description |
---|---|
$BP_FUNCTION |
Configure the function to load. If the function lives in the default package: <class> . If the function lives in their own package: <package>.<class> . Defaults to functions.Handler |
To get started you'll need to create a directory where your function will be defined.
From within this directory we require a few files to properly detect this as a Java function:
func.yaml
: We use this to configure the runtime environment variables. See the Knative Func CLI docs for more details.pom.xml
or build.gradle: These are used by the other Java buildpacks to compile your function.src/main/java/functions
: This is the default location your function will be detected. If you do choose to use another package to store your functions, you will need to define where your function is located with the BP_FUNCTION configuration for the buildpack.The Java invoker contains a readiness/liveness endpoint that can be hit at localhost:8080/actuator/health
by default. For more information, read about the Spring Boot Actuator's Kubernetes Probes.
If you want to quickly start writing your functions, take a look at the functions samples in the application accelerators samples repo.
An application developer may build an image from an exploded executable JAR. Most platforms will automatically extract provided archives.
The following command uses Maven directly to compile an executable JAR and then uses the pack
CLI to build an image from the JAR.
cd samples/java/native-image
./mvnw package
pack build samples/java-native \
--env BP_NATIVE_IMAGE=true \
--path java/native-image/java-native-image-sample/target/demo-0.0.1-SNAPSHOT.jar
If you're using Tanzu Application Platform, you'll probably only build from source.
The resulting application image will be identical to that built in the "Building a Native image with Maven" example.
The GraalVM Buildpack will provide the GraalVM JDK, including the native-image
utility (the Native image builder), and the Substrate VM.
The Native Image Buildpack uses native-image
to compile the Java bytecode into a standalone executable. The Native Image Buildpack uses the standard tools for building native images and does not depend on Spring Native support.
NoteThe
native-image
build is a memory intensive process and might be slow if insufficient memory is provided. From the prerequisites in the Spring Native reference docs: "On Mac and Windows, it is recommended to increase the memory allocated to Docker to at least 8G (and potentially to add more CPUs as well) since native-image compiler is a heavy process. See this Stackoverflow answer for more details. On Linux, Docker uses by default the resources available on the host so no configuration is needed."
The exact substrate VM version that was contributed to a given image can be read from the Bill-of-Materials.
Given an image named samples/java-native
built from one of examples above, the following command will print the exact version of the installed substrate VM.
pack inspect-image samples/java-native --bom | jq '.local[] | select(.name=="native-image-svm") | .metadata.version'
Because GraalVM is evolving rapidly you may on occasion need to, for compatibility reasons, select a specific version of the GraalVM and associated tools to use when building an image. This is not a directly configurable option like the JVM version, however, you can pick a specific version by changing the version of the Tanzu Java Native Image Buildpack you use.
The following table documents the versions available.
GraalVM version | Tanzu Java Native Image Buildpack version |
---|---|
22.3 | 6.43.0 (Paketo Java Native Image 7.44.3) |
22.2 | 6.24.1 (Paketo Java Native Image 7.26.1) |
22.1 | 6.16.2 (Paketo Java Native Image 7.16.2) |
21.3 | 4.10.0 (Paketo Java Native Image 5.12.0) |
For example, to select GraalVM v22.1:
pack build samples/native -e BP_NATIVE_IMAGE=true --buildpack paketo-buildpacks/ca-certificates --buildpack paketo-buildpacks/[email protected]
By default, the Paketo Java Native Image buildpack will use BellSoft's Native Image Toolkit. The following Paketo JVM buildpacks may be used to substitute alternate Native Image Toolkit implementations in place of the default.
JVM | Buildpack |
---|---|
BellSoft Liberica | [Paketo BellSoft Liberica Buildpack][bp/bellsoft-liberica] |
GraalVM | Paketo GraalVM Buildpack |
To use an alternative Java Native Image Toolkit, you will need to set two --buildpack
arguments to pack build
, one for the alternative Java Native Image Toolkit buildpack you'd like to use and one for the Paketo Java Native Image buildpack (in that order). This works because while you end up with two Java Native Image Toolkit buildpacks, the first one, the one you're specifying will claim the build plan entries so the second one will end up being a no-op and doing nothing.
This example will switch in the GraalVM buildpack:
pack build samples/native-image --buildpack paketo-buildpacks/graalvm --buildpack paketo-buildpacks/java-native-image`
There is one drawback to this approach. When using the method above to specify an alternative Java Native Image Toolkit vendor buildpack, this alternate buildpack ends up running before the CA certificates buildpack and therefore traffic from the alternate Java Native Image Toolkit vendor buildpack won’t trust any additional CA certs. This is not expected to impact many users because Java Native Image Toolkit buildpacks should reach out to URLs that have a cert signed by a known authority with a CA in the default system truststore.
If you have customized your Java Native Image Toolkit buildpack to download the Java Native Image Toolkit from a URL that uses a certificate not signed by a well-known CA, you can workaround this by specifying the CA certs buildpack to run first. This works because while you will end up with the CA certificates buildpack specified twice, the lifecycle is smart enough to drop the second one.
For example:
pack build samples/jar --buildpack paketo-buildpacks/ca-certificates --buildpack paketo-buildpacks/graalvm --buildpack paketo-buildpacks/java-native-image`
It does not hurt to use this command for all situations, it is just more verbose and most users can get away without specifying the CA certificates buildpack to be first.
The following environment variable configures the JVM version at build-time.
BP_JVM_VERSION
:
BP_JVM_VERSION=8
or BP_JVM_VERSION=8.*
the buildpack will install the latest patch releases of the Java 8 JDK and JRE.The Java Native Image Buildpack contains the Spring Boot Buildpack and provides the same Spring Boot features as the Java Buildpack.
Application Monitoring has been moved to a new page. Please see the Partner integrations.
The Java Native Image Buildpack will contribute a default process type that starts the application.
Execute the following commands to start the default process type using a samples/java-native
image built from any previous example command.
docker run --rm --publish 8080:8080 samples/java-native
curl -s http://localhost:8080/actuator/health
Additional arguments can be provided to the application using the container [CMD
][oci config]. In Kubernetes set CMD
using the args
field on the [container][kubernetes container resource] resource.
Execute the following command passes an additional argument to application start command, setting the port to 8081
.
docker run --rm --publish 8081:8081 samples/java-native --server.port=8081
curl -s http://localhost:8081/actuator/health
The following component buildpacks compose the Paketo Java Native Image Buildpack.
Buildpack | Required/Optional | Responsibility |
---|---|---|
Paketo GraalVM Buildpack | Required | Provides the GraalVM JDK and Native Image Substrate VM. |
Paketo Gradle Buildpack | Optional | Builds Gradle-based applications from source. |
Paketo Maven Buildpack | Optional | Builds Maven-based applications from source. |
Paketo Leiningen Buildpack | Optional | Builds Leiningen-based applications from source. |
Paketo SBT Buildpack | Optional | Builds SBT-based applications from source. |
Paketo Executable JAR Buildpack | Optional | Contributes a process Type that launches an executable JAR. |
Paketo Spring Boot Buildpack | Optional | Contributes configuration and metadata to Spring Boot applications. |
Paketo Native Image Buildpack | Required | Creates a native image from a JVM application. |
Paketo Procfile Buildpack | Optional | Allows the application to define or redefine process types with a Procfile |
Paketo Environment Variables Buildpack | Optional | Contributes arbitrary user-provided environment variables to the image. |
Paketo Image Labels Buildpack | Optional | Contributes OCI-specific and arbitrary user-provided labels to the image. |
Tanzu Java Function Buildpack | Optional | Contributes appropriate dependencies to build a function |
Java Native Image buildpack users can provide their own CA certificates and have them included in the container root truststore at build-time and runtime by following the instructions in the CA Certificates section of the configuration documentation.
Java Native Image buildpack users can set custom start processes for their app image by following the instructions in the Procfiles section of the configuration documentation.
Java Native Image buildpack users can embed launch-time environment variables in their app image by following the documentation for the Environment Variables Buildpack.
Java Native Image buildpack users can add labels to their app image by following the instructions in the Applying Custom Labels section of the configuration documentation.