ARM image doesn't include ARM binaries
Describe the issue Docker image 5.14.0 doesn't include ARM binaries inside the image.
The problem is that both docker images are built based on distroless java 17 which doesn't include ARM flavor, so java runtime include x86_64 binaries only.
You can verify that by running:
docker manifest inspect --verbose mockserver/mockserver:5.14.0
It will give same layers for 2 architectures, sizes of the images are also exactly the same.
The easiest ways to solve this in my opinion:
- Change base image to something which supports multiple architectures (e.g. openjdk official build)
- Use different base images per architecture (example) and find new base image to use for ARM64 architectures.
What you are trying to do Prevent mockserver docker failures when running on ARM CPUs See #819 and #1428
MockServer version 5.14.0
To Reproduce Steps to reproduce the issue:
- Run AWS ARM instance (e.g. t4g.nano)
- Run mockserver from the dockerhub
[ec2-user@ip-172-31-0-105 ~]$ sudo docker run mockserver/mockserver:5.14.0
Unable to find image 'mockserver/mockserver:5.14.0' locally
6.14.0: Pulling from mockserver/mockserver
0a602d5f6ca3: Pull complete
d7fbeaa2da3f: Pull complete
a1f1879bb7de: Pull complete
2afd560bd3d9: Pull complete
8a4811140f89: Pull complete
d72616bd414f: Pull complete
004a8328e2b7: Pull complete
Digest: sha256:59bf7fc611dc212f9fe07d316641bceec758f5db06df3d1ba9ac65e3569c805b
Status: Downloaded newer image for mockserver/mockserver:5.14.0
exec /usr/bin/java: exec format error
Mockserver fails to start with exec /usr/bin/java: exec format error
Expected behaviour Mockserver started successfully
MockServer Log n/a
I just noticed that in Dockerfile mockserver also includes libnetty_tcnative_linux_x86_64.so so to make truly multiarch build there might be more changes needed to the actual build process, not only base image changes.
After couple modifications I managed to build arm64 image which runs successfully on arm64 t4g.nano graviton instance.
Main changes:
- based on architecture on underlying system I am downloading either
x64_64oraarch64netty-tcnative-boringssl-static.jar-
netty-tcnative-2.0.54.Final-linux-aarch_64-fedora.jarafter unzipping hasMETA-INF/native/libnetty_tcnative_linux_aarch_64.so
-
- I moved from
gcr.io/distroless/java17:nonroottoopenjdk:17-slim
#
# MockServer Dockerfile
#
# https://github.com/mock-server/mockserver
# https://www.mock-server.com
#
ARG source=download
# build image
FROM alpine as download
# download jar
RUN apk add --update openssl ca-certificates bash wget
# REPOSITORY is releases or snapshots
ARG REPOSITORY=releases
# VERSION is LATEST or RELEASE or x.x.x
ARG VERSION=RELEASE
# see: https://oss.sonatype.org/nexus-restlet1x-plugin/default/docs/path__artifact_maven_redirect.html
ARG REPOSITORY_URL=https://oss.sonatype.org/service/local/artifact/maven/redirect?r=${REPOSITORY}&g=org.mock-server&a=mockserver-netty&c=jar-with-dependencies&e=jar&v=${VERSION}
RUN wget --max-redirect=10 -O mockserver-netty-jar-with-dependencies.jar "$REPOSITORY_URL"
# add netty-tcnative-boringssl so file
RUN if [ "$(uname -m)" = "x86_64" ]; \
then wget --max-redirect=10 -O netty-tcnative-boringssl-static.jar "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=releases&g=io.netty&a=netty-tcnative-boringssl-static&c=linux-x86_64&e=jar&v=2.0.54.Final"; \
else wget --max-redirect=10 -O netty-tcnative-boringssl-static.jar "https://repo1.maven.org/maven2/io/netty/netty-tcnative/2.0.54.Final/netty-tcnative-2.0.54.Final-linux-aarch_64-fedora.jar"; \
fi
RUN unzip netty-tcnative-boringssl-static.jar
# build image
FROM alpine as copy
# copy jar
COPY mockserver-netty-jar-with-dependencies.jar .
# add netty-tcnative-boringssl so file
RUN apk add --update openssl ca-certificates bash wget
RUN if [ "$(uname -m)" = "x86_64" ]; \
then wget --max-redirect=10 -O netty-tcnative-boringssl-static.jar "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=releases&g=io.netty&a=netty-tcnative-boringssl-static&c=linux-x86_64&e=jar&v=2.0.54.Final"; \
else wget --max-redirect=10 -O netty-tcnative-boringssl-static.jar "https://repo1.maven.org/maven2/io/netty/netty-tcnative/2.0.54.Final/netty-tcnative-2.0.54.Final-linux-aarch_64-fedora.jar"; \
fi
RUN unzip netty-tcnative-boringssl-static.jar
FROM ${source} as intermediate
FROM openjdk:17-slim
# maintainer details
LABEL maintainer="James Bloom <[email protected]>"
# expose ports.
EXPOSE 1080
# copy in jar
COPY --from=intermediate mockserver-netty-jar-with-dependencies.jar /
COPY --from=intermediate META-INF/native/libnetty_tcnative_linux_*.so /usr/lib/
# don't run MockServer as root
RUN useradd -ms /bin/bash nonroot
USER nonroot
ENTRYPOINT ["java", "-Dfile.encoding=UTF-8", "-cp", "/mockserver-netty-jar-with-dependencies.jar:/libs/*", "-Dmockserver.propertyFile=/config/mockserver.properties", "org.mockserver.cli.Main"]
ENV SERVER_PORT 1080
CMD []
@bbednarek this looks interesting I'll try to incorporate these changes
Great findings @bbednarek!
If you want to use a distroless with arm64 you can use: gcr.io/distroless/java17-debian11:nonroot. Then you can omit RUN useradd -ms /bin/bash nonroot
Thanks @Karamell. It works as a charm. @jamesdbloom I will raise PR to fix this issue.
Just FYI our fork has working ARM images. Feel free to check them out.