◀Back
Containerize a Native Executable and Run in a Container
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 containerize 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.
Download a 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.
Prerequisite
Make sure you have installed a GraalVM JDK. The easiest way to get started is with SDKMAN!. For other installation options, visit the Downloads section.
-
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.git
- Change directory to native-image/containerize/:
cd graalvm-demos/native-image/containerize
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 stop the application.
Containerize the Native Executable
The generated native executable is platform-dependent.
-
Containerize the native executable using the following commands.
- On Linux, containerize the native executable generated in the previous step:
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 .
- On Linux, containerize the native executable generated in the previous step:
- 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 also build fully static native executables and package them directly into tiny containers such as scratch or distroless containers.