- MacOS 10.15.4 64-bit (Catalina)
 - Ubuntu Server 19.04 64-bit (eoan)
 - Raspbian GNU/Linux 10 32-bit (buster)
 - Docker/Buildx v0.3.1-tp-docker
 
Hardware:
- MacBook:
 - MacOS 64-bit OS
 - Docker 19.03.8
 - Raspberry Pi 1, 2, 3 or 4:
 - Raspbian 10 32-bit OS
 - Docker 18.09.1
 - Raspberry Pi 3 or 4:
 - Ubuntu Server 64-bit OS
 - Docker 19.03.6
 
- Verify that Docker images are platform dependent (single-arch).
 - Learn how to build multi-arch docker images that can be used on several platforms (e.g. amd64, arm64, arm).
 
Prerequisites:
- An externally-accessible insecure Docker Registry running on the MacOS machine. See how to configure it here
 - Configure Docker to use experimental features
 - Configure Docker to work with insecure-registry
 
Build a simple Docker Image:
- Let's start creating a simple Dockerfile to build an image:
 - mkdir ~/docker-test
 - cd ~/docker-test
 - nano ./Dockerfile
 - FROM ubuntu:18.04
 - CMD ["sleep", "infinity"]
 
- Build an image on a MacBook and tag as AMD64:
 
- docker login 192.168.1.107:5000
 - docker build -t 192.168.1.107:5000/docker-test:amd64 .
 
- Push the image to the private docker registry:
 - docker push 192.168.1.107:5000/docker-test:amd64
 
- Try to run a container based on this image:
 - Machine: MacBook
 - docker run --entrypoint bash -it 192.168.1.107:5000/docker-test:amd64
 - root@d465832164be:/# uname -m
 - x86_64
 - Machine: Raspberry Pi running Ubuntu 64-bit OS
 - docker run --entrypoint bash -it 192.168.1.107:5000/docker-test:amd64
 - standard_init_linux.go:211: exec user process caused "exec format error"
 - Machine: Raspberry Pi running Raspbian 32-bit OS
 - docker run --entrypoint bash -it 192.168.1.107:5000/docker-test:amd64
 - standard_init_linux.go:207: exec user process caused "exec format error"
 
- Build an image on Raspberry Pi running Raspbian 32-bit OS and tag as ARM32
 
- Copy the Dockerfile to a folder on Raspberry Pi 32-bit OS machine and `cd` to it:
 - docker login 192.168.1.107:5000
 - docker build -t 192.168.1.107:5000/docker-test:arm32 .
 
- Push the image to the private docker registry:
 - docker push 192.168.1.107:5000/docker-test:arm32
 
- Try to run a container based on this image:
 - Machine: MacBook
 - docker run --entrypoint bash -it 192.168.1.107:5000/docker-test:arm32
 - root@ead4869f18b9:/# uname -m
 - armv7l
 - Machine: Raspberry Pi running Ubuntu 64-bit OS
 - docker run --entrypoint bash -it 192.168.1.107:5000/docker-test:arm32
 - root@95b80ff7d56f:/# uname -m
 - aarch64
 - Machine: Raspberry Pi running Raspbian 32-bit OS
 - docker run --entrypoint bash -it 192.168.1.107:5000/docker-test:arm32
 - root@d8bbc13939e5:/# uname -m
 - armv7l
 
- Build an image on Raspberry Pi running Ubuntu 64-bit OS and tag as ARM64:
 
- Copy the Dockerfile to a folder on Raspberry Pi 32-bit OS machine and `cd` to it:
 - docker login 192.168.1.107:5000
 - docker build -t 192.168.1.107:5000/docker-test:arm64 .
 
- Push the image to the private docker registry:
 - docker push 192.168.1.107:5000/docker-test:arm64
 
- Try to run a container based on this image:
 - Machine: MacBook
 - docker run --entrypoint bash -it 192.168.1.107:5000/docker-test:arm64
 - root@feb84b4dfc5c:/# uname -m
 - aarch64
 - Machine: Raspberry Pi running Ubuntu 64-bit OS
 - docker run --entrypoint bash -it 192.168.1.107:5000/docker-test:arm64
 - root@c9e0aa8eb98e:/# uname -m
 - aarch64
 - Machine: Raspberry Pi running Raspbian 32-bit OS
 - docker run --entrypoint bash -it 192.168.1.107:5000/docker-test:arm64
 - standard_init_linux.go:207: exec user process caused "exec format error"
 
- Listing Docker images:
 - docker images | grep 192.168.1.107
 - 192.168.1.107:5000/docker-test arm32 51c74aa10614 46.7MB
 - 192.168.1.107:5000/docker-test arm64 c6dd32c882f6 57.7MB
 - 192.168.1.107:5000/docker-test amd64 32458c475b0e 64.2MB
 - docker image inspect 192.168.1.107:5000/docker-test:arm32 | grep Architecture
 - "Architecture": "arm",
 - docker image inspect 192.168.1.107:5000/docker-test:arm64 | grep Architecture
 - "Architecture": "arm64",
 - docker image inspect 192.168.1.107:5000/docker-test:amd64 | grep Architecture
 - "Architecture": "amd64",
 
- Conclusions:
 - The images built with `docker build` command are platform dependent.
 - An image built on ARM32 platform CAN be used on ARM64 platform.
 - An image built on ARM64 platform can NOT be used on ARM32 platform.
 - The Docker Desktop (for MacOS and Windows) has QEMU emulation and can run many platform images, regardless of the platform the image was built for.
 
![]()  | 
| QEMU emulation for the arm/v6, arm/v7 and arm64 Docker images | 
Build Multi-arch simple Docker Images:
- Let's start creating a simple Dockerfile to build an image:
 - mkdir ~/docker-test-multiarch
 - cd ~/docker-test-multiarch
 - nano ./Dockerfile
 - FROM ubuntu:18.04
 - ARG TARGETPLATFORM
 - ARG BUILDPLATFORM
 - RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM"
 - CMD ["sleep", "infinity"]
 
- Build multi-architecture images on a MacBook or Linux:
 - cd ~/docker-test-multiarch
 - Log in on the registry server:
 - docker login -u <registry-user> [registry_url]
 - enter the registry password
 - Create a new instance of an isolated builder:
 - docker buildx create --name multiarch-builder --platform linux/amd64,linux/arm64
 - Switches the current builder instance. Build commands invoked after this command will run on a specified builder.
 - docker buildx use multiarch-builder
 - [Optional] docker buildx ls
 - [Optional] docker buildx inspect multiarch-builder
 - Build the images for the desired platforms (architectures):
 - docker buildx build -t <registry-url>/<image-name>:<tag> [-f Dockerfile] --platform linux/amd64,linux/arm64 --push .
 
- Cleanup the environment:
 - docker buildx use default
 - docker buildx stop multiarch-builder
 - docker buildx rm multiarch-builder
 
References:
- Ubuntu Download IoT
 - Raspbian Download
 - Docker
 - Docker BuildX CLI Plugin
 - Docker Registry Server
 

