First of all thanks a lot for the great way to compile native applications with Spring Boot 3!
I just created a ticket https://github.com/paketo-buildpacks/base-builder/issues/652 to support arm64 arch builder maintained by paketo.
So my suggestion would be for the spring-boot-maven-plugin that it somehow detects the arch at which the plugin is executed and hands this over to each docker pull. (see description of the linked ticket). This option should be configurable so that there is the chance to override it. (e.g. arch or something like that).
This configuration should be available for all tags like builder / runImage / buildpacks.
New example configuration:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>
<arch>linux/arm64</arch>
<from>paketobuildpacks/builder:tiny</from>
</builder>
<runImage>
<arch>linux/arm64</arch>
<from>paketobuildpacks/run:latest</from>
</runImage>
<env>
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
</env>
<buildpacks>
<buildpack>
<arch>linux/arm64</arch>
<from>gcr.io/paketo-buildpacks/java-native-image:7.8.1</from>
</buildpack>
</buildpacks>
</image>
</configuration>
</plugin>
This way you can either let the spring-boot-maven-plugin detect the arch, or choose a different arch for each image.
WDYT?
See also: https://github.com/paketo-buildpacks/stacks/issues/51#issuecomment-1024982024
Comment From: mhalbritter
As far as I understand it, docker would pull a linux/arm64 container image if the packeto buildpacks would provide one. Are you sure it always pulls the linux/amd64 one even if there would be a linux/arm64 available?
Comment From: klopfdreh
You can provide docker images for multiple platforms with the same tag. So imagine you have an image paketobuildpacks/builder:tiny. paketobuildpacks/builder is the image itself and tiny is the tag. This image can be pushed for multiple platforms with this tag - for example linux/amd64 and in addition also for linux/arm64.
As far as I can see there is no hint of what platform is used if you do not provide any --platform option. My assumption is that the platform is used you are currently working on. See: https://docs.docker.com/engine/reference/commandline/image_pull/#options
An example is azul/zulu-openjdk (https://hub.docker.com/r/azul/zulu-openjdk/tags) here you can see for example 15-latest is provided for linux/amd64 and for linux/arm64/v8
So if I want to build an linux/amd64 image I could not do this with a Apple M1 MacBook, but if the implementation of the plugin would be changed I could let docker pull the amd64 images and build the images for this architecture via Rosetta2.
Maybe it would be good to not add any --platform parameter if it is not configured, but use it when you configured it the way I described at the description from this issue.
Comment From: scottfrederick
@klopfdreh It seems that your goal with this idea is to be able to build an image on one architecture that is able to run on a different architecture (for example, build an image on a linux/arm64 machine and have the resulting image be compatible with a linux/amd64 machine). If this is the goal, the suggested approach is not likely to work.
The builder and buildpack images that are provided to the Spring Boot build plugins are loaded into the local Docker daemon and processes in the image are executed. As we've seen from many issue reports to this project and the Paketo project, running an image that is built for AMD architecture on an ARM device like a Mac M1/M2 is not reliable (even with Rosetta). For some, the image building process hangs, for others it runs very slowly. I tried running a CNB builder that is built for the ARM architecture on my Intel machine and I got an error like exec format error. We would not want to provide an option for users to configure this type of arrangement given how unreliable it is.
Aside from this concern, the builder and buildpack images do not determine the base architecture of the generated image - only the run image determines this. There is a relationship between build images (not to be confused with builder images) and run images in a CNB stack (see the CNB docs for more details). Just specifying a run image with an architecture won't succeed unless the builder includes a stack that is compatible with the run image.
There might be a way to achieve the goal of building an image on one architecture that targets another architecture, but specifying the architecture of each of the image configured in the Spring Boot plugins is not the answer. I think we'll need to wait and see what a multi-arch builder image from Paketo looks like, and possibly if/how other CNB platforms support something like this, before deciding how we would support it in the Spring Boot build plugins.
Comment From: klopfdreh
Hey @scottfrederick - I just have one last question. As you can see I linked an issue at paketo builders. Does the spring-boot-maven-plugin always pull the right builder image if two platforms are available? If yes I agree to add an option which could cause issues would not be a good option.
Comment From: scottfrederick
The Spring Boot plugins make a Docker Engine API call to the local Docker daemon. without providing a platform option, so it's really up to the daemon. The Docker daemon does appear to pull the image matching the platform that it is running on.
I tested that using a multi-arch CNB builder derived from the Paketo builder available here (more information on that here). When I configured my Spring Boot build to use that builder, the version for my architecture was pulled.
I also used this to validate my assumptions on the effects of using a builder for the wrong architecture. If you docker pull [builder image] --platform [wrong arch for your local machine], specify that builder image in your build file, and also specify <pullPolicy>NEVER</pullPolicy> in your bulid file, then you're likely to have a bad experience when building the image.
Comment From: SSmale
Was there a solution to this? I would like to be able to build for arm64 but not sure how to do it
Comment From: scottfrederick
@SSmale You just need a CNB builder that supports arm64. An experimental one is available here: https://github.com/dashaun/paketo-arm64.
Comment From: klopfdreh
Hey, maybe it is worth to think about it as docker released rosetta support for their docker desktop. With this you may be able to build x86-64 arch images on your AArch64 machine. To configure the plugin maybe useful in this case. See: https://docs.docker.com/desktop/release-notes/#4250
Rosetta is now Generally Available for all users on macOS 13 or later. It provides faster emulation of Intel-based images on Apple Silicon. To use Rosetta, see Settings. Rosetta is enabled by default on macOS 14.1 and later.