Arm64 Docker image?

Hi,

In the times of the Apple Silicon chip, wouldn’t it make sense to provide an arm64 image for the Axon Server? I built one myself, but it would be convenient to just have one ready on Docker Hub.

Thanks,
Markus

5 Likes

I agree. That would be great!

Hey Markus,
great idea! We will need to look at a good base for this because there are no distroless Java images for arm64 yet. I see Google has “gcr.io/distroless/base:latest-arm64”, as well as “nonroot-arm64” and “debug-arm64” and “debug-nonroot-arm64”, so we would have to reproduce their Java installation and test if that works. That is going to be a bit of a thing because Apple does not provide VM images to run on non-Apple hardware. Finding a generic ARM VM in the cloud shouldn’t be a problem though. Do you have any experience showing that that is a valid test for running on Apple hardware?

Cheers,
Bert

Hey,

I didn’t run comprehensive tests with my image - just checked if my application would work as expected.

The base image I used is: bellsoft/liberica-openjdk-debian:15

If you provide an image, I can do some tests here on my notebook.

Thanks,
Markus

Has there been any movement on this? I would also be able to test the image on my notebook. At this point running Axon Server is not possible on an M1 MacBook.

Jonathan,
We’ve been looking at the Google situation, but it looks like there’s no real movement on the multi-platform part towards the language-specific builds. I’ve also looked at RedHat’s ubi8 builds because they appear to be well maintained and frequently updated with security patches. The downside is that they are significantly larger than the Distroless images, but for a Docker deployment on developer laptops, having a complete environment with shell and tools might actually be an advantage.

I’ll let you know when we have a build ready.

Cheers,
Bert

1 Like

Would it be possible to provide some sort of documentation on how to set up your own arm64 Axon Server Docker image similar to this GitHub - AxonIQ/running-axon-server: The files that go with the "Running Axon Server" Blog series.? This way the community could test the image and add to it.

Jonathan,
the current image is built using the Jib Maven plugin, by running the Axon Server SE build with “-Pdocker”. This uses the “gcr.io/distroless/java:11” as its base and creates an “exploded JAR” installation in the root. The OpenJDK image for Java 11 (“openjdk:11”) is supposed to support the arm architecture. Can you verify that with e.g. a “docker run --rm -it openjdk:11 java -version”?

Bert

Hi Bert, I was able to run the command and pull the jdk version. When trying to build my own image using this Dockerfile running-axon-server/Dockerfile at 065a1729a4dd9830ac44ce6b8f58ff52b1c79d31 · AxonIQ/running-axon-server · GitHub I am getting some odd errors related to Spring, I’m not sure how to resolve those. By the way, AWS EC2 also supports arm64 AWS Graviton - Amazon Web Services, that should allow you to test the image.

Not having seen your Dockerfile or logs, I would hazard to guess that you ran Axon Server under user “axonserver”, and the errors are concerning rights on the volumes.

1 Like

Hi all, is there any progress on a new image? A month later I find this thread, trying to solve the same problem. Running on M1 with Rosetta 2 installed, I get the same error others have reported:

docker run --rm --name axonserver --platform linux/amd64 -p 8024:8024 -p 8124:8124 axoniq/axonserver
Unable to find image ‘axoniq/axonserver:latest’ locally
latest: Pulling from axoniq/axonserver

Digest: sha256:ecef7e434219c584fb56352d052dc8074401ed66ec41c711ec854ec0499e6bab
Status: Downloaded newer image for axoniq/axonserver:latest
_ ____
/ \ __ _____ _ __ / | ___ _ ____ _____ _ __
/ _ \ \ / / _ | ’
\
_ \ / _ \ '\ \ / / _ \ '|
/ ___ \ > < () | | | |) | __/ | \ V / __/ |
/
/ _/
/__/|| ||____/ _|| _/ ___||
Standard Edition Powered by AxonIQ

version: 4.5.6
2021-08-24 14:41:26.087 INFO 1 — [ main] io.axoniq.axonserver.AxonServer : Starting AxonServer using Java 11.0.12 on 81c80db0ed41 with PID 1 (/app/classes started by root in /)
2021-08-24 14:41:26.098 INFO 1 — [ main] io.axoniq.axonserver.AxonServer : No active profile set, falling back to default profiles: default
2021-08-24 14:41:30.011 WARN 1 — [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [io.axoniq.axonserver.AxonServer]; nested exception is java.io.FileNotFoundException: class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class] cannot be opened because it does not exist
2021-08-24 14:41:30.123 ERROR 1 — [ main] o.s.boot.SpringApplication : Application run failed

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [io.axoniq.axonserver.AxonServer]; nested exception is java.io.FileNotFoundException: class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class] cannot be opened because it does not exist
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189) ~[spring-context-5.3.3.jar:5.3.3]

Hi all there, is any news about axon image for Mac m1 architecture ? Now I have the same error as Assen Kolov have.

docker run --rm --name axonserver --platform linux/amd64 -p 8024:8024 -p 8124:8124 axoniq/axonserver
_ ____
/ \ __ _____ _ __ / | ___ _ ____ _____ _ __
/ _ \ \ / / _ | ’
\
_ \ / _ \ '\ \ / / _ \ '|
/ ___ \ > < () | | | |) | __/ | \ V / __/ |
/
/ _/
/__/|| ||____/ _|| _/ ___||
Standard Edition Powered by AxonIQ

version: 4.5.6
2021-09-13 12:39:26.020 INFO 1 — [ main] io.axoniq.axonserver.AxonServer : Starting AxonServer using Java 11.0.12 on 396064f9ca7e with PID 1 (/app/classes started by root in /)
2021-09-13 12:39:26.031 INFO 1 — [ main] io.axoniq.axonserver.AxonServer : No active profile set, falling back to default profiles: default
2021-09-13 12:39:30.001 WARN 1 — [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [io.axoniq.axonserver.AxonServer]; nested exception is java.io.FileNotFoundException: class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class] cannot be opened because it does not exist
2021-09-13 12:39:30.105 ERROR 1 — [ main] o.s.boot.SpringApplication : Application run failed

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [io.axoniq.axonserver.AxonServer]; nested exception is java.io.FileNotFoundException: class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class] cannot be opened because it does not exist
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:336) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:252) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:285) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:99) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:751) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:569) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.2.jar:2.4.2]
at io.axoniq.axonserver.AxonServer.main(AxonServer.java:55) ~[classes/:na]
Caused by: java.io.FileNotFoundException: class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:180) ~[spring-core-5.3.3.jar:5.3.3]
at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:55) ~[spring-core-5.3.3.jar:5.3.3]
at org.springframework.core.type.classreading.SimpleMetadataReader.(SimpleMetadataReader.java:49) ~[spring-core-5.3.3.jar:5.3.3]
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103) ~[spring-core-5.3.3.jar:5.3.3]
at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.createMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:86) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.getMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:73) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:81) ~[spring-core-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser.asSourceClass(ConfigurationClassParser.java:696) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getRelated(ConfigurationClassParser.java:1090) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getAnnotationAttributes(ConfigurationClassParser.java:1071) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser.collectImports(ConfigurationClassParser.java:549) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser.getImports(ConfigurationClassParser.java:522) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:311) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:199) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:304) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175) ~[spring-context-5.3.3.jar:5.3.3]
… 14 common frames omitted

Ok, sorry to have kept all of you waiting.

As it looks like Google is not moving with respect to Distroless images for ARM, I have pushed two images based on “openjdk:11-slim”, built on an ARM VM in AWS. Please let me know if these work, so I can make a proper announcement.

The tags are:

  • axoniq/axonserver:4.5.7-dev-arm
    This image provides Axon Server SE version 4.5.7, running as user “root” in “/axonserver”.
  • axoniq/axonserver:4.5.7-dev-nonroot-arm
    This image provides Axon Server SE version 4.5.7, running as user “axonserver” in “/axonserver”.

The exported volumes are “/axonserver/config”, “/axonserver/data”, “/axonserver/events”, “/axonserver/exts”, and “/axonserver/plugins”. See the Dockerfile example in the Running Axon Server repository for information on this.

Cheers,
Bert Laverman

Hi Bert,

Great! Thanks a lot.

I tested the arm image today and it seems to run well on my M1 Mac.

I’d suggest to tag the image architecture independent, so that compose files would be the same and docker would pick the right image by itself?

Cheers,
Markus

Yes, I was already looking at that, but need to experiment with the buildx and manifest features to ensure we can do simply multi-architecture builds. However, that would mean we’d leave Distroless which feels like a shame due to their lean size.

Bert

Hello Bert,

Thanks, I used the arm64 based image and it works very well on my system as well.

Also, an updated docker image that supports Java 17, tagged 4.5.8, has been uploaded to the docker hub. Please, can you provide an equivalent version for arm64 based processor?

Regards,
Jelil

Jelil,
The image on Docker Hub with name “axoniq/axonserver:4.5.8” (which is the same as “axoniq/axonserver:latest” at the moment) has been built using Java 11:

     _                     ____
    / \   __  _____  _ __ / ___|  ___ _ ____   _____ _ __
   / _ \  \ \/ / _ \| '_ \\___ \ / _ \ '__\ \ / / _ \ '__|
  / ___ \  >  < (_) | | | |___) |  __/ |   \ V /  __/ |
 /_/   \_\/_/\_\___/|_| |_|____/ \___|_|    \_/ \___|_|
 Standard Edition                        Powered by AxonIQ

version: 4.5.8
2021-11-01 09:08:33.927  INFO 1 --- [           main] io.axoniq.axonserver.AxonServer          : Starting AxonServer using Java 11.0.12 on 92825f7359fc with PID 1 (/app/classes started by root in /)

So where did you get the JDK 17 build?

Bert

Hello Bert,

I got the info from the AxonServer update notification (check the below image), but I think got it wrong.

But, can you please provide an amd64 based image of “axoniq/axonserver:4.5.8 on the docker hub?

Jelil

Ok, that explains. We noted a dependency in Axon Server SE was causing troubles when using a Java 17 JDK to run it. The version update fixed this, removing the issue. The image is however still using JDK 11 to run.

We now have a full collection on Docker Hub, including Java 17 ones.