At work, I currently use a MacBook Pro with an Intel chipset and some of my colleagues have upgraded to ones with M1 chipset which is of arm64 or aarch64 architecture. Then expectedly I need to build some Docker images for both architectures.
I’ve done some multi-arch Docker stuff before so this is not really a challenge. But there’s still something learned in the process.
There are some useful Docker environment variables for multi-arch purposes:
- BUILDPLATFORM as the name suggests it has the platform name of the host. So if I build stuff with an Intel or AMD platform this variable will be set to
linux/amd64
- TARGETPLATFORM is a combination of TARGETOS, TARGETARCH and TARGETVARIANT, and is set from the
--platform=linux/amd64
switch such asdocker buildx build --platform=linux/amd64 .
- TARGETOS usually is just
linux
. I won’t touch Windows containers - TARGETARCH can be
amd64
orarm64
. For M1 MacBook this should bearm64
- TARGETVARIANT could be
v7
orv8
but I don’t think this is as useful as the first 2.
The environment variables above are very useful in a multi-arch Dockerfile, for example, to install a platform specific JDK version:
# example from Dockerfile for Elasticsearch
FROM centos:8 AS builder
ARG TARGETPLATFORM
ENV PATH /usr/share/elasticsearch/bin:$PATH
ENV JAVA_HOME /opt/jdk-15.0.1+9
# install platform specfic openJDK
RUN case ${TARGETPLATFORM} in \
"linux/amd64") JDK_ARCH=x64 ;; \
"linux/arm64") JDK_ARCH=aarch64 ;; \
esac && \
for iter in {1..10}; do curl -L -s -S https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.1%2B9/OpenJDK15U-jdk_${JDK_ARCH}_linux_hotspot_15.0.1_9.tar.gz | tar -C /opt -zx && \
exit_code=0 && break || exit_code=\$? && echo "download error: retry $iter in 10s" && sleep 10; done; \
(exit $exit_code)
Then the Dockerfile can be used in a docker buildx
command such as
docker buildx build --platform linux/amd64,linux/arm64 -t my.registry/image-name:tag --push .
The result docker image should be able to run as native architecture (arm64) on a M1 MacBook.