◀Table of Contents
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 scenario.
To support container-based development, there are several GraalVM images available, depending on the platform, the architecture, the Java version, and the edition:
- GraalVM Enterprise container images are in Oracle Container Registry
- GraalVM Community container images in GitHub Container Registry
Note on a Sample Application
For the demo you will use the same Spring Boot “Jibber” application” as in the Build a Spring Boot Application into a Native Executable guide.
You are expected to pass all steps in that tutorial, have a native executable version of the sample application (target/jibber
) and seen it working.
Prerequisites
- Docker
The output of a native executable is platform-dependent. If you use a Mac or Windows, to build a Docker image containing your native executable you need to build a native executable within a Docker container – so you need a container with a JDK distribution. If you are a Linux user, you can just pass a native executable to Docker and use the simplest slim or distroless container, depending on static libraries your application is linked against. For example:
```
FROM gcr.io/distroless/base
ARG APP_FILE
EXPOSE 8080
COPY target/${APP_FILE} app
ENTRYPOINT ["/jibber"]
``` For user's convenience, Dockerfiles are provided with the demo.
We will show how to containerise a Java application with Docker on macOS.
For that, we will use ghcr.io/graalvm/jdk:ol8-java17
which is a size compact GraalVM Community container image with the GraalVM JDK pre-installed.
This Dockerfile will be applied.
-
From application root folder, run this command to create a native executable within a container and then build a Docker image containing that native executable:
docker build -f Dockerfiles/Dockerfile \ --build-arg APP_FILE=./target/jibber \ -t localhost/jibber:native.01 .
It will take several minutes to set up Maven in the container and do rest of the job.
- Query Docker to look at your newly built image:
docker images | head -n2
You should see a new image listed.
-
Run the image as follows:
docker run --rm --name native -d -p 8080:8080 localhost/jibber:native.01
-
Then call the endpoint using the
curl
command in the same console window:curl http://localhost:8080/jibber
You should receive a nonsense verse in the style of the poem Jabberwocky. You can take a look at how long the application took to startup by looking at the logs:
docker logs <CONTAINER ID>
You can also query Docker to get the size of the produced container:
docker images localhost/jibber:native.01
The difference will be more visible if you build a Docker image of the same Spring Boot application containing a JAR file instead of a native executable, and compare images startup times and file sizes.
On Linux, you can shrink your container size even more. With GraalVM Native Image you have the ability to build a statically linked native executable by packaging the native executable directly into an empty Docker image, also known as a scratch container. Continue to Build a Static or Mostly-Static Native Executable guide to learn more.