Spring Boot 2.6.3 ARM64 Image
Tags: springboot, java, raspberrypi
Published: 2022-01-31 17:40:45

---
title: Spring Boot 2.6.3 ARM64 Image
published: true
date: 2022-01-31 02:55:02 UTC
tags: springboot,java,raspberrypi
canonical_url: https://dashaun.com/posts/springboot-arm64-image/
---

## Spring Boot on Raspberry Pi 4b 8gb

The purpose of this article is to create a Spring Boot (2.6.3) native image for arm64.  In my case, the Raspberry Pi Zero 2W.  The Raspberry Pi Zero 2W only has 512mb of SDRAM. Because of the small footprint of the `Zero 2W` I want to be as efficient as possible.

We will build a very simple Spring Boot app again, but add `Spring Native` to compile a native executable. 

A bunch of this information is repeated from the previous article.  Image creation happens on the Raspberry Pi 4.  The resulting image can be deployed to a Raspberry Pi Zero 2 W.


## Install ARM64, RaspiOS Bullseye, on Raspberry Pi 4 with 8gb

For this example I'm using [RaspiOS Bullseye](https://downloads.raspberrypi.org/raspios_arm64/images/raspios_arm64-2021-11-08/2021-10-30-raspios-bullseye-arm64.zip).  I still recommend using the [Raspberry Pi Imager](https://www.raspberrypi.com/software/) for the install.

## Update, upgrade and install

```shell
sudo apt update
sudo apt upgrade -y
sudo apt install zip
```

## Install docker

```shell
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
#you might need to logout and login to get the group assignment
docker run hello-world
```

## Install SDKMAN

```shell
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk version
```

## Install a JDK

Install the latest version of the JDK.

```shell
sdk list java
sdk install java 22.0.0.2.r17-grl
java -version
```

## Create simple Spring Boot application
Use the Spring Initializer web API to create a simple example.

The parameters below:

- name the artifact
- choose Java 17
- include the "web","actuator" and "spring native" dependencies
- use latest version of Spring Boot by default

```shell
mkdir demo
cd demo
curl https://start.spring.io/starter.tgz -d groupId=dev.dashaun -d artifactId=spring-pi -d name=spring-pi -d packageName=dev.dashaun.spring-pi -d dependencies=web,actuator,native -d javaVersion=17 | tar -xzf -
```

## Two changes

[Starters requiring special build configuration](https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/#_starters_requiring_special_build_configuration).

Swap out the tomcat version:

```xml=
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-websocket</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.experimental</groupId>
    <artifactId>tomcat-embed-programmatic</artifactId>
    <version>${tomcat.version}</version>
</dependency>
```

>Exclude io.micrometer:micrometer-core when metrics are not used for optimized footprint.

```xml=
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
```

## Milestone reached

At this point I can generate an ARM64 `native` executable using the native build tools.

Install the native-image extensions for the JDK:
```shell
gu install native-image
```

Build the application with Maven
```shell=
./mvnw -Pnative -DskipTests package
```

I didn't panic when I saw the warnings during compilation, because I had read the documenation.

[From the Spring Native Documentation](https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/)

> During the native compilation, you will see a lot of WARNING: Could not register reflection metadata messages. They are expected and will be removed in a future version, see #502 for more details.

There will be a `target/spring-pi` executable, 63mb in my example.

Copy that to your `Raspberry Pi Zero 2 W` and it works as expected!

## Keep going

How am I supposed to handle that native executable?  Where do I put it?  Do I make it a Github release package?  Do people use Github releases in their CI/CD?

```
  "The container image is the new artifact."
      - Cora Iberkleid
```

## Getting Unexpected Help

I was on a path to create my own buildpack for ARM64, but I was going the long way.

Daniel Mikusa created a better way.

[dmikusa-pivotal/paketo-arm64](https://github.com/dmikusa-pivotal/paketo-arm64)

I followed his repository and created my own versions of the cloud native buildpacks.  I pushed those images to my public docker repo.

## Building an Image

The default builder `<builder>paketobuildpacks/builder:tiny</builder>` doesn't have arm64 images yet.
So edit `pom.xml` to use `<builder>dashaun/native-builder:focal-arm64</builder>` instead.

Now you can create a native arm64 image using the spring boot plugin:

```shell
./mvnw -Pnative spring-boot:build-image -DskipTests
```

When that is complete, you can run the image:

```shell
docker run -p 8080:8080 spring-pi:0.0.1-SNAPSHOT
```

> Our applicaiton is now running on port 8080

## Summary

Building arm64 images on a Raspberry Pi 4 is not fast.  Being able to run arm64 native images on a Raspberry Pi Zero 2 W has me super excited.  I've made the cloud native buildpack images available via Docker Hub.  I've also created an example repository on Github.

For me, this opens the door for a software supply chain, that creates native arm64 images for my Spring Boot projects.  This also makes kubernetes on arm64 devices, as small as the Raspberry Pi Zero 2 W, much more interesting!

## Links

- https://github.com/dmikusa-pivotal/paketo-arm64
- https://github.com/dashaun/spring-boot-native-pi
- https://hub.docker.com/r/dashaun/native-builder
- https://hub.docker.com/r/dashaun/stack-build
- https://hub.docker.com/r/dashaun/stack-run
- https://hub.docker.com/r/dashaun/spring-pi-native