DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Securing Your Software Supply Chain with JFrog and Azure
Register Today

Trending

  • Scaling Site Reliability Engineering (SRE) Teams the Right Way
  • Hiding Data in Cassandra
  • Constructing Real-Time Analytics: Fundamental Components and Architectural Framework — Part 2
  • 10 Traits That Separate the Best Devs From the Crowd

Trending

  • Scaling Site Reliability Engineering (SRE) Teams the Right Way
  • Hiding Data in Cassandra
  • Constructing Real-Time Analytics: Fundamental Components and Architectural Framework — Part 2
  • 10 Traits That Separate the Best Devs From the Crowd
  1. DZone
  2. Coding
  3. Java
  4. Guide to Creating and Containerizing Native Images

Guide to Creating and Containerizing Native Images

In this article, we will learn how to turn Java applications into native images and then containerize them for further deployment in the cloud.

Dmitry Chuyko user avatar by
Dmitry Chuyko
·
Apr. 18, 23 · Tutorial
Like (1)
Save
Tweet
Share
6.93K Views

Join the DZone community and get the full member experience.

Join For Free

Native Image technology is gaining traction among developers whose primary goal is to accelerate startup time of applications. In this article, we will learn how to turn Java applications into native images and then containerize them for further deployment in the cloud. We will use:

  • Spring Boot 3.0 with baked-in support for Native Image as the framework for our Java application;

  • Liberica Native Image Kit (NIK) as a native-image compiler;

  • Alpaquita Stream as a base image.

Building Native Images from Spring Boot Apps

Installing Liberica NIK

It would be best to utilize a powerful computer with several gigabytes of RAM to work with native images. Opt for a cloud service provided by Amazon or a workstation so as not to overload the laptop. We will be using Linux bash commands further on because bash is a perfect way of accessing the code remotely. macOS commands are similar. As for Windows, you can use any alternative, for instance, bash included in the Git package for Windows.

Download Liberica Native Image Kit for your system. Choose a Full version for our purposes.

Unpack tar.gz with:

tar -xzvf ./bellsoft-liberica.tar.gz

Now, put the compiler to $PATH with:

GRAALVM_HOME=/home/user/opt/bellsoft-liberica export PATH=$GRAALVM_HOME/bin:$PATH

Check that Liberica NIK is installed:

java -version openjdk version "17.0.5" 2022-10-18 LTS

OpenJDK Runtime Environment GraalVM 22.3.0 (build 17.0.5+8-LTS)

OpenJDK 64-Bit Server VM GraalVM 22.3.0 (build 17.0.5+8-LTS, mixed mode, sharing)


native-image --version

GraalVM 22.3.0 Java 17 CE (Java Version 17.0.5+8-LTS)

If you get the error "java: No such file or directory" on Linux, you installed the binary for Alpine Linux, not Linux. Check the binary carefully.

Creating a Spring Boot Project

The easiest way to create a new Spring Boot project is to generate one with Spring Initializr. Select Java 17, Maven, JAR, and Spring SNAPSHOT-version (3.0.5 at the time of writing this article), then fill in the fields for project metadata. We don’t need any dependencies.
Add the following code to you main class:
System.out.println("Hello from Native Image!");

Spring has a separate plugin for native compilation, which utilizes multiple context dependent parameters under the hood. Let’s add the required configuration to our pom.xml file: 

XML
 
<profiles>

    <profile>

        <id>native</id>

        <build>

            <plugins>

                <plugin>

                    <groupId>org.graalvm.buildtools</groupId>

                    <artifactId>native-maven-plugin</artifactId>

                    <executions>

                        <execution>

                            <id>build-native</id>

                            <goals>

                                <goal>compile-no-fork</goal>

                            </goals>

                            <phase>package</phase>

                        </execution>

                    </executions>

                </plugin>

            </plugins>

        </build>

    </profile>

</profiles>

Let’s build the project with the following command:

./mvnw clean package -Pnative

The resulting native image is in the target directory.

Write a Dockerfile

We need to write a Dockerfile to generate a Docker image container. Put the following file into the application folder:

Dockerfile
 
FROM bellsoft/alpaquita-linux-base:stream-musl

COPY target/native-image-demo .

CMD ["./native-image-demo"]

Where we:

  1. Create an image with Alpaquita Linux base image (the native image doesn’t need a JVM to execute);

  2. Copy the app into the new image;

  3. Run the program inside the container.

We can also skip the step with Liberica NIK installation and we build a native image straight in a container, which is useful when the development and deployment architectures are different. For that purpose, create another folder and put there your application and the following Dockerfile:

Dockerfile
 
FROM bellsoft/liberica-native-image-kit-container:jdk-17-nik-22.3-stream-musl as builder

WORKDIR /home/myapp

ADD native-image-demo /home/myapp/native-image-demo

RUN cd native-image-demo && ./mvnw clean package -Pnative

FROM bellsoft/alpaquita-linux-base:stream-musl

WORKDIR /home/myapp

COPY --from=builder /home/myapp/native-image-demo/target/native-image-demo .

CMD ["./native-image-demo"]

Where we:

  1. Specify the base image for Native Image generation;

  2. Point to the directory where the image will execute inside Docker;

  3. Copy the program to the directory;

  4. Build a native image;

  5. Create another image with Alpaquita Linux base image (the native image doesn’t need a JVM to execute);

  6. Specify the executable directory;

  7. Copy the app into the new image;

  8. Run the program inside the container. 

Build a Native Image Container

To generate a native image and containerize it, run:

docker build .

Note that if you use Apple M1, you may experience troubles with building a native image inside a container.

Check that the image was create with the following command:

Dockerfile
 
docker images

REPOSITORY   TAG       IMAGE ID       CREATED          SIZE

<none>       <none>    8ebc2a97ef8e   18 seconds ago   45.2MB

Tag the newly created image:

docker tag 8ebc2a97ef8e nik-example

Now you can run the image with:

docker run -it --rm 8ebc2a97ef8e

Hello from Native Image!

Conclusion

Native image containerization is as simple as creating Docker container images of standard Java apps. Much trickier is to migrate a Java application to Native Image.

We used a simple program that didn’t require any manual configuration. But dynamic Java features (Reflection, JNI, Serialization, etc.) are not supported by GraalVM, so you have to make the native-image tool aware of them.

Docker (software) Java (programming language) Spring Boot Cloud

Published at DZone with permission of Dmitry Chuyko. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Scaling Site Reliability Engineering (SRE) Teams the Right Way
  • Hiding Data in Cassandra
  • Constructing Real-Time Analytics: Fundamental Components and Architectural Framework — Part 2
  • 10 Traits That Separate the Best Devs From the Crowd

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: