Compiling your Quarkus applications to native executables
Abstract
Preface Copy linkLink copied to clipboard!
As an application developer, you can use Red Hat build of Quarkus to create microservices written in Java that run on OpenShift and serverless environments. Applications compiled to native executables have small memory footprints and fast startup times.
This guide shows you how to compile the Quarkus Getting Started project into a native executable and how to configure and test the native executable. You will need the application created in Getting started with Quarkus.
Building a native executable with Red Hat build of Quarkus covers:
- Building a native executable with a single command using a container runtime such as Podman or Docker
- Creating a custom container image using the produced native executable
- Creating a container image using the OpenShift Docker build strategy
- Deploying the Quarkus native application to OpenShift
- Configuring the native executable
- Testing the native executable
Prerequisites
Have OpenJDK (JDK) 11 installed and the
JAVA_HOMEenvironment variable set to specify the location of the Java SDK.- Log in to the Red Hat Customer Portal to download Red Hat build of Open JDK from the Software Downloads page.
- An OCI (Open Container Initiative) compatible container runtime, such as Podman or Docker.
A completed Quarkus Getting Started project.
- To learn how to build the Quarkus Getting Started project, see Getting started with Quarkus.
-
Alternatively, you can download the Quarkus quickstart archive or clone the
Quarkus QuickstartsGit repository. The sample project is in thegetting-starteddirectory.
Providing feedback on Red Hat documentation Copy linkLink copied to clipboard!
We appreciate your feedback on our technical content and encourage you to tell us what you think. If you’d like to add comments, provide insights, correct a typo, or even ask a question, you can do so directly in the documentation.
You must have a Red Hat account and be logged in to the customer portal.
To submit documentation feedback from the customer portal, do the following:
- Select the Multi-page HTML format.
- Click the Feedback button at the top-right of the document.
- Highlight the section of text where you want to provide feedback.
- Click the Add Feedback dialog next to your highlighted text.
- Enter your feedback in the text box on the right of the page and then click Submit.
We automatically create a tracking issue each time you submit feedback. Open the link that is displayed after you click Submit and start watching the issue or add more comments.
Thank you for the valuable feedback.
Making open source more inclusive Copy linkLink copied to clipboard!
Red Hat is committed to replacing problematic language in our code, documentation, and web properties. We are beginning with these four terms: master, slave, blacklist, and whitelist. Because of the enormity of this endeavor, these changes will be implemented gradually over several upcoming releases. For more details, see our CTO Chris Wright’s message.
Chapter 1. Producing a native executable Copy linkLink copied to clipboard!
You can produce a native executable from your Quarkus application using a container runtime such as Podman or Docker. Quarkus produces a binary executable using a builder image, which you can use together with the Red Hat Universal Base Images RHEL8-UBI and RHEL8-UBI minimal. Red Hat build of Quarkus 1.11 uses registry.access.redhat.com/quarkus/mandrel-20-rhel8:20.3 as a default for the quarkus.native.builder-image property.
The native executable for your application contains the application code, required libraries, Java APIs, and a reduced version of a virtual machine (VM). The smaller VM base improves the startup time of the application and produces a minimal disk footprint.
Procedure
Open the Getting Started project
pom.xmlfile and verify that it includes thenativeprofile:Copy to Clipboard Copied! Toggle word wrap Toggle overflow NoteUsing Quarkus
nativeprofile allows you to run both the native executable and the native image tests.Build a native executable using one of the following methods:
Build a native executable with Docker:
./mvnw package -Pnative -Dquarkus.native.container-build=true
./mvnw package -Pnative -Dquarkus.native.container-build=trueCopy to Clipboard Copied! Toggle word wrap Toggle overflow Build a native executable with Podman:
./mvnw package -Pnative -Dquarkus.native.container-build=true -Dquarkus.native.container-runtime=podman
./mvnw package -Pnative -Dquarkus.native.container-build=true -Dquarkus.native.container-runtime=podmanCopy to Clipboard Copied! Toggle word wrap Toggle overflow These commands create the
getting-started-*-runnerbinary in thetargetdirectory.ImportantCompiling a Quarkus application to a native executable consumes a lot of memory during analysis and optimization. You can limit the amount of memory used during native compilation by setting the
quarkus.native.native-image-xmxconfiguration property. Setting low memory limits might increase the build time. For more details, refer to Native executable configuration properties.
Run the native executable:
./target/getting-started-*-runner
./target/getting-started-*-runnerCopy to Clipboard Copied! Toggle word wrap Toggle overflow When you build the native executable the
prodprofile is enabled and the Quarkus native tests run using theprodprofile. You can change this using thequarkus.test.native-image-profileproperty.
Chapter 2. Creating a custom container image Copy linkLink copied to clipboard!
You can create a container image from your Quarkus application using one of the following methods:
- Creating a container manually
- Creating a container using the OpenShift Docker build
Compiling a Quarkus application to a native executable consumes a lot of memory during analysis and optimization. You can limit the amount of memory used during native compilation by setting the quarkus.native.native-image-xmx configuration property. Setting low memory limits might increase the build time.
2.1. Creating a container manually Copy linkLink copied to clipboard!
This section shows you how to manually create a container image with your application for Linux X86_64. When you produce a native image using the Quarkus Native container it creates an executable that targets the Linux X86_64 operating system. If your host operating system is different from this, you will not be able to run the binary directly and you will need to create a container manually.
Your Quarkus Getting Started project includes a Dockerfile.native in the src/main/docker directory with the following content:
The Dockerfiles use UBI as a base image. This base image was designed to work in containers. The Dockerfiles use the minimal version of the base image to reduce the size of the produced image.
Procedure
Build a native Linux executable using one of the following methods:
Build a native executable with Docker:
./mvnw package -Pnative -Dquarkus.native.container-build=true
./mvnw package -Pnative -Dquarkus.native.container-build=trueCopy to Clipboard Copied! Toggle word wrap Toggle overflow Build a native executable with Podman:
./mvnw package -Pnative -Dquarkus.native.container-build=true -Dquarkus.native.container-runtime=podman
./mvnw package -Pnative -Dquarkus.native.container-build=true -Dquarkus.native.container-runtime=podmanCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Build the container image using one of the following methods:
Build the container image with Docker:
docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/getting-started .
docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/getting-started .Copy to Clipboard Copied! Toggle word wrap Toggle overflow Build the container image with Podman
podman build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/getting-started .
podman build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/getting-started .Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Run the container:
Run the container with Docker:
docker run -i --rm -p 8080:8080 quarkus-quickstart/getting-started
docker run -i --rm -p 8080:8080 quarkus-quickstart/getting-startedCopy to Clipboard Copied! Toggle word wrap Toggle overflow Run the container with Podman:
podman run -i --rm -p 8080:8080 quarkus-quickstart/getting-started
podman run -i --rm -p 8080:8080 quarkus-quickstart/getting-startedCopy to Clipboard Copied! Toggle word wrap Toggle overflow
2.2. Creating a container using the OpenShift Docker build Copy linkLink copied to clipboard!
You can create a container image for your Quarkus application using the OpenShift Docker build strategy. This strategy creates a container using a build configuration in the cluster.
Prerequisites
- You have access to a Red Hat OpenShift Container Platform cluster and the latest version of the OpenShift CLI (oc) is installed. For information about installing oc, see the "Installing the CLI" section of the Installing and configuring OpenShift Container Platform clusters guide.
- A URL for the OpenShift API endpoint.
Procedure
Log in to the OpenShift CLI:
oc login -u <username_url>
oc login -u <username_url>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Create a new project in OpenShift:
oc new-project <project_name>
oc new-project <project_name>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Create a build config based on the
src/main/docker/Dockerfile.nativefile:cat src/main/docker/Dockerfile.native | oc new-build --name <build_name> --strategy=docker --dockerfile -
cat src/main/docker/Dockerfile.native | oc new-build --name <build_name> --strategy=docker --dockerfile -Copy to Clipboard Copied! Toggle word wrap Toggle overflow Build the project:
oc start-build <build_name> --from-dir .
oc start-build <build_name> --from-dir .Copy to Clipboard Copied! Toggle word wrap Toggle overflow Deploy the project to OpenShift:
oc new-app <build_name>
oc new-app <build_name>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Expose the services:
oc expose svc/<build_name>
oc expose svc/<build_name>Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Chapter 3. Native executable configuration properties Copy linkLink copied to clipboard!
Configuration properties define how the native executable is generated. You can configure your Quarkus application using the application.properties file.
Configuration properties
The following table lists the configuration properties that you can set to define how the native executable is generated:
| Property | Description | Type | Default |
|---|---|---|---|
|
| Additional arguments to pass to the build process. | list of string | |
|
| Enables HTTP URL handler. This allows you to do URL.openConnection() for HTTP URLs. | boolean |
|
|
| Enables HTTPS URL handler. This allows you to do URL.openConnection() for HTTPS URLs. | boolean |
|
|
| Adds all security services to the native image. | boolean |
|
|
| Adds all character sets to the native image. This increases image size. | boolean |
|
|
| Contains the path of the Graal distribution. | string |
|
|
| Contains the path of the JDK. |
| |
|
| The maximum Java heap used to generate the native image. | string | |
|
| Waits for a debugger to attach to the build process before running the native image build. This is an advanced option for those familiar with GraalVM internals. | boolean |
|
|
| Publishes the debug port when building with docker and debug-build-process is true. | boolean |
|
|
| Restarts the native image server. | boolean |
|
|
| Enables isolates to improve the memory management. | boolean |
|
|
| Creates a JVM based fallback image if native image fails. | boolean |
|
|
| Uses native image server. This can speed up compilation but can cause changes to drop due to cache invalidation issues. | boolean |
|
|
| Automatically registers all META-INF/services entries. | boolean |
|
|
| Dumps the bytecode of all proxies for inspection. | boolean |
|
|
| Builds using a container runtime. Docker is used by default. | boolean |
|
|
| The docker image to build the image. | string |
|
|
| The container runtime used build the image. For example, Docker. | string | |
|
| Options to pass to the container runtime. | list of string | |
|
| Enables VM introspection in the image. | boolean |
|
|
| Enables full stack traces in the image. | boolean |
|
|
| Generates reports on call paths and included packages/classes/methods. | boolean |
|
|
| Reports exceptions with a full stack trace. | boolean |
|
|
| Reports errors at runtime. This may cause your application to fail at runtime if you are using unsupported feature. | boolean |
|
|
|
A comma separated list of globs to match resource paths that should be added to the native image. Use slash ( | list of string | |
|
|
Enables debug and generates debug symbols in a separate .debug file. When used with | boolean |
|
Supported glob features and its description
The following table lists the supported glob features and its description:
| Character | Feature description |
|
|
Matches a possibly empty sequence of characters that does not contain slash ( |
|
|
Matches a possibly empty sequence of characters that might contain slash ( |
|
| Matches one character, but not slash. |
|
| Matches one character from the range specified in the bracket, but not slash. |
|
| Matches one character from the range specified in the bracket, but not slash. |
|
| Matches one character not specified in the bracket; does not match slash. |
|
| Matches one character outside the range specified in the bracket; does not match slash. |
|
| Matches any of the alternating tokens separated by comma; the tokens may contain wildcards, nested alternations and ranges. |
|
|
The escape character. There are three levels of escaping: |
3.1. Configuring memory consumption for Quarkus native compilation Copy linkLink copied to clipboard!
Compiling a Quarkus application to a native executable consumes a lot of memory during analysis and optimization. You can limit the amount of memory used during native compilation by setting the quarkus.native.native-image-xmx configuration property. Setting low memory limits might increase the build time.
Procedure
Use one of the following methods to set a value for the
quarkus.native.native-image-xmxproperty to limit the memory consumption during the native image build time:Using the
application.propertiesfile:quarkus.native.native-image-xmx=<maximum_memory>
quarkus.native.native-image-xmx=<maximum_memory>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Setting system properties:
mvn -Pnative -Dquarkus.native.container-build=true -Dquarkus.native.native-image-xmx=<maximum_memory>
mvn -Pnative -Dquarkus.native.container-build=true -Dquarkus.native.native-image-xmx=<maximum_memory>Copy to Clipboard Copied! Toggle word wrap Toggle overflow This command builds the native executable with Docker. Add
-Dquarkus.native.container-runtime=podmanargument to use Podman.
For example, to set the memory limit to 6 GB, enter quarkus.native.native-image-xmx=6g. The value must be a multiple of 1024 greater than 2MB. Append the letter m or M to indicate megabytes, or g or G to indicate gigabytes.
Chapter 4. Testing the native executable Copy linkLink copied to clipboard!
Test the application running in the native mode to test the functionality of the native executable. Use @NativeImageTest annotation to build the native executable and run test against the http endpoints.
Procedure
Open the
pom.xmlfile and verify that thenativeprofile contains the following elements:Copy to Clipboard Copied! Toggle word wrap Toggle overflow The
failsafe-maven-pluginruns integration test and indicates the location of the produced native executable.Open the
src/test/java/org/acme/quickstart/NativeGreetingResourceIT.javafile and verify that it includes the following content:Copy to Clipboard Copied! Toggle word wrap Toggle overflow Run the test:
./mvnw verify -Pnative
./mvnw verify -PnativeCopy to Clipboard Copied! Toggle word wrap Toggle overflow The following example shows the output of this command:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow NoteQuarkus waits for 60 seconds for the native image to start before automatically failing the native tests. You can change this duration using the
quarkus.test.native-image-wait-timesystem property.You can extend the wait time using the following command where
<duration>is the wait time in seconds:./mvnw verify -Pnative -Dquarkus.test.native-image-wait-time=<duration>
./mvnw verify -Pnative -Dquarkus.test.native-image-wait-time=<duration>Copy to Clipboard Copied! Toggle word wrap Toggle overflow
4.1. Excluding tests when running as a native executable Copy linkLink copied to clipboard!
When you run tests against your native application, you can only interact with its HTTP endpoints. Tests do not run natively, therefore they cannot link against your application’s code like they can when running on the JVM.
You can share your test class between JVM and native executions and exclude certain tests with the @DisabledOnNativeImage annotation to run them only on the JVM.
4.2. Testing an existing native executable Copy linkLink copied to clipboard!
You can test against the existing executable build. This allows you to run multiple sets of tests in stages on the binary after it has been build.
Procedure
Run a test against an already built native executable:
./mvnw test-compile failsafe:integration-test
./mvnw test-compile failsafe:integration-testCopy to Clipboard Copied! Toggle word wrap Toggle overflow This command runs the test against the existing native image using Failsafe Maven Plugin.
Alternatively, you can specify the path to the native executable with the following command where
<path>is the native image path:./mvnw test-compile failsafe:integration-test -Dnative.image.path=<path>
./mvnw test-compile failsafe:integration-test -Dnative.image.path=<path>Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Chapter 5. Additional resources Copy linkLink copied to clipboard!
Revised on 2021-06-30 13:18:34 UTC