Skip to main content

Command Palette

Search for a command to run...

Native image containers with Rockcraft plugins

Updated
4 min read
Native image containers with Rockcraft plugins

In this series, I have shown how Rockcraft’s Maven and Gradle plugins make the task of producing development-time container images of your application, effortless and iteration-friendly.

The need to run a Java application within a bare-minimal runtime comes from the cloud-native and edge-computing worlds, where optimizing away unwanted dependencies to reduce the application’s memory footprint is a common effort. In that context, the Rockcraft plugins let us create custom application runtime images for non-modular and modular Java applications.

There is another problem that afflicts all kinds of Java applications. By virtue of the platform-independent design of the Java platform, applications often suffer from a slow/delayed startup. There is a category of modern Java applications, especially from the cloud-native world, with sub-second startup-time requirements, where this problem becomes critical.

GraalVM Native Image offers a promising solution to the slow-startup problem. GraalVM compiles an application into a platform-native executable binary, enabling application startup right at launch. With compile-time class loading, ahead-of-time compilation of code and minimal-to-no garbage collection, GraalVM native image suits short-lived Java applications very well.

💡
You may refer to the official Ubuntu documentation for native compile with GraalVM Community Edition.

Native image containers with the Rockcraft Maven/Gradle plugins

For your Maven and Gradle based applications, the Rockcraft plugins let you create container images packaging the self-sufficient native-image binary produced by GraalVM. The native image compilation happens on the host.

If you don’t have the pre-requisite setup for Rockcraft, please follow instructions here.

Step 1: Installing GraalVM Community Edition for JDK

For Ubuntu versions 24.04 and above, GraalVM Community Edition is available as a snap package. For the purpose of this demo exercise, we need a GraalVM installation.

snap install graalvm-jdk --channel=v21
💡
The stable and betachannels let you install the latest and development GraalVM CE versions respectively. As the name suggests, channel v21 installs GraalVM for JDK 21.

This command installs a GraalVM JDK at /snap/graalvm-jdk/current/graalvm-ce.

Step 2: Clone your project

Let’s use the spring-petclinic project for this demo.

git clone https://github.com/spring-projects/spring-petclinic && \
cd spring-petclinic

Step 3: Configure the native compilation plugin

For Maven-based projects please add the following build plugin. The spring-petclinic project has this build plugin added.

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
</plugin>

For a Gradle-based project add this plugin. The spring-petclinic project this plugin added.

plugin {
  ...
  id 'org.graalvm.buildtools.native' version '0.10.6'
}

Step 4: Configure the Rockcraft plugin

Make sure the Rockcraft Maven plugin is also added to the pom.xml in your Maven project.

            <plugin>
                <groupId>io.github.rockcrafters</groupId>
                <artifactId>rockcraft-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <configuration>
                            <createService>false</createService>
                        </configuration>
                        <goals>
                            <goal>create-rock</goal>
                            <goal>build-rock</goal>
                            <goal>push-rock</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

For your Gradle project, make sure the Rockcraft plugin is configured after the GraalVM plugin.

plugin {
  ...
  id 'org.graalvm.buildtools.native' version '0.10.6'
  id 'io.github.rockcrafters.rockcraft' version '1.2.1'
}

Step 5: Running maven/gradle

The GraalVM plugins will need the location of a GraalVM installation in your environment. Use the GRAALVM_HOME environment variable to point to the installation we did in step 1.

export GRAALVM_HOME=/snap/graalvm-jdk/current/graalvm-ce

For Maven projects, run this command:

mvn -Pnative native:compile -DskipTests install
💡
I am skipping the tests because a container-based test, irrelevant to this demo, fails in my environment.

The -Pnative native:compile options trigger the native image compilation using the GraalVM installation pointed to by GRAALVM_HOME.

For Gradle-based projects run the following command using the packaged gradlew wrapper.

./gradlew nativeCompile push-rock -i

Step 6: Run the application native image

The newly pushed docker image can now be located

$ docker image ls
REPOSITORY            TAG              IMAGE ID       CREATED                 SIZE
petclinic             3.5.0-SNAPSHOT   4e46eb04bc44   About a minute ago      336MB
petclinic             latest           4e46eb04bc44   About a minute ago      336MB

Notice the bloated size! The space-time trade-off is obvious.

Now, let’s locate the native executable in this image and run it.

$ docker run petclinic exec pebble ls /*petclinic*
spring-petclinic
$ docker --network=host run petclinic exec /spring-petclinic


              |\      _,,,--,,_
             /,`.-'`'   ._  \-;;,_
  _______ __|,4-  ) )_   .;.(__`'-'__     ___ __    _ ___ _______
 |       | '---''(_/._)-'(_\_)   |   |   |   |  |  | |   |       |
 |    _  |    ___|_     _|       |   |   |   |   |_| |   |       | __ _ _
 |   |_| |   |___  |   | |       |   |   |   |       |   |       | \ \ \ \
 |    ___|    ___| |   | |      _|   |___|   |  _    |   |      _|  \ \ \ \
 |   |   |   |___  |   | |     |_|       |   | | |   |   |     |_    ) ) ) )
 |___|   |_______| |___| |_______|_______|___|_|  |__|___|_______|  / / / /
 ==================================================================/_/_/_/

:: Built with Spring Boot :: 3.5.0
...
...
2025-08-29T15:40:36.664Z  INFO 18 --- [           main] o.s.s.petclinic.PetClinicApplication : 
Started PetClinicApplication in 0.229 seconds (process running for 0.233)

The application comes up in ~0.23 seconds and is reachable at http://localhost:8080.

Thanks for reading! Below are the screen-casts for the Maven and Gradle workflows.

Java application containers on Ubuntu

Part 2 of 6

The Maven and Gradle plugins for Rockcraft let you build Ubuntu container images for your Java application through a maven goal or a gradle task. They let you build and test apps in the very same container they would be eventually deployed in.

Up next

Creating jlink'd application images using Gradle

The previous post showed how a self-contained runtime image for a non-modular application could be packaged into a container using the Badass Runtime plugin and the Rockcraft Gradle plugin. Speaking of modules as defined by the Java Platform Module S...

More from this blog

Java for Ubuntu

14 posts