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. 🙂