Learn how to push your Java app to VMware Tanzu Application Service for VMs (TAS for VMs) and how to configure your app to use the Java Native Image Buildpack. VMware discourages using the Java Native Image Buildpack with production workloads while it is in beta.
Cloud Native Buildpacks include support for building native image apps. You can pass in your source code or a compiled JAR and Cloud Native Buildpacks installs the required tools and builds a compatible image.
Clone the example repository from GitHub:
git clone https://github.com/paketo-buildpacks/samples
cd samples/java/native-image/java-native-image-sample
Build the example image:
./mvnw package
pack build apps/native-image -p target/demo-0.0.1-SNAPSHOT.jar -e BP_NATIVE_IMAGE=true -B paketobuildpacks/builder:tiny
For more information about building with Cloud Native Buildpacks, see Getting Started in the Spring Native documentation.
This section describes how to deploy a Java app with native image support using Cloud Native Buildpacks.
To deploy an app compiled using the steps from the previous section to TAS for VMs, you can deploy the image directly using TAS for VMs’s Docker support. If Docker support is deactivated, you can extract the native image binary from the container image and deploy the app using the binary buildpack.
To deploy the app from an image:
Publish your image. You can do this in a number of ways. For example, you can use the --publish
flag to pack build
with docker tag
and docker push
, or through any other means of publishing a container image to a registry.
Validate that your foundation supports deploying Docker images by running the following command and confirming that diego_docker
is set to enabled
. If it is set to disabled
, you cannot use this deployment option.
cf feature-flags
For example:
$ cf feature-flags Retrieving status of all flagged features as [email protected]... features state user_org_creation disabled private_domain_creation enabled app_bits_upload enabled app_scaling enabled route_creation enabled service_instance_creation enabled diego_docker enabled set_roles_by_username enabled unset_roles_by_username enabled task_creation enabled env_var_visibility enabled space_scoped_private_broker_creation enabled space_developer_env_var_visibility enabled service_instance_sharing enabled hide_marketplace_from_unauthenticated_users disabled resource_matching enabled
Push your app by running:
cf push -o registry.example.com/apps/native-image native-image-app
To extract and deploy your app using the binary buildpack:
Create a script to extract the files:
#!/bin/bash
if [ -z "$1" ] || [ -z "$2" ]; then
echo "USAGE: extract.sh image-name full-main-class"
echo
exit 1
fi
CONTAINER_ID=$(docker create "$1")
mkdir -p ./out
docker cp "$CONTAINER_ID:/workspace/$2" "./out/$2"
docker rm "$CONTAINER_ID" > /dev/null
This script is optional, but illustrates the process of extracting the binary file. It runs docker create
and docker cp
to extract the file from the image, followed by docker rm
to remove the containerd. You can do this manually, or you can use any other tools for interacting with a container image.
Run the extract script:
$ ./extract.sh apps/native-image io.paketo.demo.Demoapp
$ file ./out/io.paketo.demo.Demoapp
io.paketo.demo.Demoapp: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=05cb81992f3859c9653a9ef6a691e798a9c48b9b, with debug_info, not stripped
The extract script places the binary in a directory called out
under the current working directory. You can run file
to examine it and confirm that it is a 64-bit Linux executable.
Push and run the compiled binary by running the following command. You can adjust other properties or use a manifest.yml
file to deploy as well.
cf push -b binary_buildpack -m 256M -p ./out -c ./io.paketo.demo.Demoapp native-image
Follow these procedures to use the Java Native Image Buildpack.
The Java Native Image Buildpack is based on the Paketo Java Native Image Buildpack. The Paketo Documentation for the Buildpack describes how to push your Java app.
For more in-depth documentation, see the Tanzu documentation for the Java Native Image Buildpack.
To push an app with the Java Native Image Buildpack, you must follow these steps:
Push the app code without starting the app, and configure a high-memory value.
cf push myApp \
-b java_native_image_cnb_beta -s tanzu-jammy-full-stack \
--no-start -m 8G
Before you can stage the app, you must set the environment variables. Additionally, the buildpack uses a lot of memory.
Set the memory value to at least 4 GB but ideally 8 GB of memory.
Set this required environment variable for Java Native Image applications.
cf set-env myApp BP_NATIVE_IMAGE true
Depending on the specifics for the app, other environment variables might be required.
Start the app:
cf start myApp
The following examples are based on common use cases.
During step 2, you set the BP_NATIVE_IMAGE
environment variable. You might also set the following variables:
cf set-env myApp BP_MAVEN_BUILD_ARGUMENTS \
"-Dmaven.test.skip=true --no-transfer-progress package -Pnative"
cf set-env myApp BP_JVM_VERSION 17
During step 2, you set the BP_NATIVE_IMAGE
environment variable. You might also set the following variable:
cf set-env myApp BP_MAVEN_ACTIVE_PROFILES native
No additional environment variables are necessary to deploy Spring Boot apps with Gradle.
During step 2, you set the BP_NATIVE_IMAGE
environment variable. You might also set the following variables:
cf set-env myApp BP_MAVEN_BUILD_ARGUMENTS "-Dquarkus.package.type=native-sources \
-Dmaven.test.skip=true package"
cf set-env myApp BP_MAVEN_BUILT_ARTIFACT "target/native-sources"
cf set-env myApp BP_NATIVE_IMAGE_BUILD_ARGUMENTS_FILE= native-sources/native-image.args"
cf set-env myApp BP_NATIVE_IMAGE_BUILT_ARTIFACT "<PATH-TO-JAR-FILE>"
cf set-env myApp BP_JVM_VERSION=17
This version of TAS for VMs supports Java Native Image CNB 7.6.1.
Join the #buildpacks channel in our Slack community if you need help.