◀Back
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.
Sample Application
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.
Prerequisites
-
Download and install the latest Oracle GraalVM from Downloads. The easiest option is to use SDKMAN!. Run the following command to install Oracle GraalVM for JDK 17:
sdk install java 17.0.8-graal
-
Install and run a Docker-API compatible container runtime such as Rancher Desktop, Docker, or Podman.
-
Clone the GraalVM Demos repository:
git clone https://github.com/graalvm/graalvm-demos
-
Change directory to the demo directory:
cd spring-native-image
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
The
-Pnative
profile 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
&
:./target/benchmark-jibber &
-
Call the endpoint using
curl
:curl http://localhost:8080/jibber
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
curl
:curl http://localhost:8080/jibber
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>
Summary
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.