Build Multi-arch Docker Images on Ubuntu Linux


Since I’ve made my Raspberry PI Kubernetes cluster hybrid, now I have good reasons to build multi-arch(which means multi CPU architecture) Docker images so I don’t care if my pod is deployed to a Raspberry PI node or a X86 node.

I followed a lot of instructions from this guide and finally made it work on my Ubuntu Linux laptop. Here are the relevant steps for Ubuntu:

First, just in case, the package docker.io needs to be installed with

# installation
sudo apt install docker.io

# add current user to the docker group, so you don't need to sudo to use docker commands
# and you might need to logout and login again to let this be effective
sudo usermod -a -G docker $(whoami)

# verification
docker version
Client:
 Version:           19.03.8
...

I’ve followed this tutorial to install buildx on Ubuntu. The exact commands are

# instructions to build the buildx plugin for docker CLI
export DOCKER_BUILDKIT=1
docker build --platform=local -o . git://github.com/docker/buildx
mkdir -p ~/.docker/cli-plugins
mv buildx ~/.docker/cli-plugins/docker-buildx

# verification
docker buildx create --help

Usage:  docker buildx create [OPTIONS] [CONTEXT|ENDPOINT]
...

A simplest “Hello world” golang app will be used to build this multi-arch docker image

# main.go
package main

import (
  "fmt"
)

func main() {
  fmt.Println("Hello!")
}

The Dockerfile for this golang app looks like

ARG ARCH=
FROM ${ARCH}golang:1.13.1 AS builder

ENV CGO_ENABLED=0 GOOS=linux
WORKDIR /app
COPY . .
RUN go build -a -installsuffix cgo -o hello main.go

FROM scratch

WORKDIR /app
COPY --from=builder /app/hello .

ENTRYPOINT ["/app/hello"]

This can be tested with the default docker build command just to iron out any error before going into multi-arch. The buildx command will be like

docker buildx build --push --platform linux/arm/v7,linux/arm64/v8,linux/amd64 -t <docker user>/<repo>:<tag> .

It might take a while to build all 3 images. After that the same image should be able to run on AMD64 or ARM platforms.

# in AMD64 or ARM environment
docker run --rm <docker user>/<repo>:<tag>

EDIT: When there’s some strange errors with buildx such as

#8 23.71 Error while loading /usr/sbin/dpkg-split: No such file or directory       
# or
#13 0.187 Can't open perl script "adduser": No such file or directory             

A potential fix is a set of commands

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
docker buildx create --name multiarch --driver docker-container --use
docker buildx inspect --bootstrap

🙂