◀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
- Change directory to spring-native-image/:
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 stop the application.
Containerize the Native Executable
The generated native executable is platform-dependent.
-
Containerize the native executable using the following command:
- On Linux, containerize 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 .
- On Linux, containerize the native executable generated in the previous step using the following command:
- 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.