Containerise a Native Executable and Run in a Docker Container
Docker containers provide the flexibility of development environments to match a production environment, to help isolate your application, and to minimize overhead. For self-contained executables, generated with GraalVM Native Image, containers are an obvious deployment choice.
To support container-based development, there are several GraalVM container images available, depending on the platform, the architecture, the Java version, and the edition:
- Oracle GraalVM container images, available in Oracle Container Registry (OCR) under the GraalVM Free Terms and Conditions (GFTC) license.
- GraalVM Community Edition container images published in the GitHub Container Registry.
This guide shows how to containerise a native executable for your Java application. You will use a GraalVM container image with Native Image to compile a Java application ahead-of-time into a native executable.
This guide uses the Spring Boot 3 Native Image Microservice example.
The example is a minimal REST-based API application, built on top of Spring Boot 3.
If you call the HTTP endpoint
/jibber, it will return some nonsense verse generated in the style of the Jabberwocky poem, by Lewis Carroll.
sdk install java 17.0.8-graal
Clone the GraalVM Demos repository:
git clone https://github.com/graalvm/graalvm-demos
Change directory to the demo directory:
Build and Run as a Native Executable
With the built-in support for GraalVM Native Image in Spring Boot 3, it has become much easier to compile a Spring Boot 3 application into a native executable.
Build a native executable:
./mvnw native:compile -Pnative
-Pnativeprofile is used to generate a native executable for your platform. This will generate a native executable called benchmark-jibber in the target directory.
Run the native executable and put it into the background by appending
Call the endpoint using
You should get a random nonsense verse.
Bring the application to the foreground using
fg, and then enter
<CTRL-c>to terminate the application.
Containerise the Native Executable
The generated native executable is platform-dependent.
Containerise the native executable using the following command:
On Linux, containerise the native executable generated in the previous step using the following command:
docker build -f Dockerfiles/Dockerfile.native --build-arg APP_FILE=benchmark-jibber -t jibber-benchmark:native.0.0.1-SNAPSHOT .
On MacOS, Windows, or Linux, use multistage Docker builds to build a native executable inside a container, and package the native executable in a lightweight container image:
docker build -f Dockerfiles/Dockerfile -t jibber-benchmark:native.0.0.1-SNAPSHOT .
Run the application:
docker run --rm --name native -p 8080:8080 jibber-benchmark:native.0.0.1-SNAPSHOT
From a new terminal window, call the endpoint using
It should generate a random nonsense verse.
To stop the application, first get the container id using
docker ps, and then run:
docker rm -f <container_id>
To delete the container images, first get the image id using
docker images, and then run:
docker rmi -f <image_1_id> <image_n_id>
In this guide, you saw how to use GraalVM container images to containerize a native executable for your Java application.
With GraalVM Native Image you can build a statically linked native executable by packaging the native executable directly into tiny containers such as scratch or distroless images. Continue to Build a Static or Mostly-Static Native Executable guide to learn more.