Using Docker Buildx to Build Images for Multiple System Architectures

Docker Buildx is a docker CLI plug-in that extends the docker command to support the functionality provided by Moby BuildKit. Provides the same user experience as docker build and adds many new features.
BuildKit is a next-generation image building component with many main features. This article mainly uses its feature of compiling multiple system architectures.
URL:https://github.com/moby/buildkit
It should be noted that this feature is only available for Docker v19.03+.

This article will explain how to use Buildx to build images for various system architectures.
Before you start, you have already installed 64-bit Docker under Linux system (major distributions) by default.
At the time of writing this article, the latest version number of Docker is 19.03.13.

$ docker version
Client: Docker Engine - Community
 Version:           19.03.13
 API version:       1.40
 Go version:        go1.13.15
 Git commit:        4484c46d9d
 Built:             Wed Sep 16 17:03:45 2020
 OS/Arch:           linux/amd64
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          19.03.13
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       4484c46d9d
  Built:            Wed Sep 16 17:02:21 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.3.7
  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

1. Enable Buildx

The buildx command is an experimental feature, so you need to enable it first.
In the content returned by checking the Docker version above, ifExperimental: trueThe words indicate that this feature has been turned on. This next step can be omitted.
Edit the ~/.docker/config.json file and add the following content (the following demonstration is applicable when the .docker directory does not exist in advance)

$ mkdir ~/.docker
$ cat > ~/.docker/config.json <<EOF
{
"experimental": "enabled"
}
EOF

Under Linux/macOS or by setting environment variables (not recommended):

$ export DOCKER_CLI_EXPERIMENTAL=enabled

2. Create a new builder instance

Available in Docker 19.03+ version docker buildx build The command uses BuildKit to build the image.This command supports --platform Parameters can simultaneously build Docker images that support multiple system architectures, greatly simplifying the construction steps.

Since Docker's default builder instance does not support specifying multiple --platform we must first create a new builder instance.

$ docker buildx create --name mybuilder --driver docker-container

Returns the new builder instance name, which is “mybuilder”

mybuilder

Use the newly created builder instance

$ docker buildx use mybuilder

View existing builder instances

$ docker buildx ls
NAME/NODE    DRIVER/ENDPOINT             STATUS   PLATFORMS
mybuilder *  docker-container
  mybuilder0 unix:///var/run/docker.sock inactive 
default      docker
  default    default                     running  linux/amd64, linux/386

Docker does not support arm architecture images under the Linux/amd64 system architecture, so we can run a new container (emulator) to support this feature. Docker desktop version does not require this setting.
method one:

$ docker run --rm --privileged docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64

Note: docker/binfmt can refer to the URL:https://hub.docker.com/r/docker/binfmt/tags Get the latest image

Method two (recommended):

$ docker run --rm --privileged tonistiigi/binfmt --install all

Go to the reference website:https://hub.docker.com/r/tonistiigi/binfmt Get the latest image.Currently (updated on 2021/04/20) Qemu version: 5.0.0

3. Create a new Dockerfile file

To build images for multiple system architectures, a supporting Dockerfile is also required.
Below is a sample Dockerfile.
Reference links:https://github.com/teddysun/across/blob/master/docker/kms/Dockerfile.architecture

The content of the Dockerfile file is as follows:

FROM --platform=$TARGETPLATFORM alpine:latest AS builder
WORKDIR /root
RUN apk add --no-cache git make build-base && \
    git clone --branch master --single-branch https://github.com/Wind4/vlmcsd.git && \
    cd vlmcsd/ && \
    make

FROM --platform=$TARGETPLATFORM alpine:latest
LABEL maintainer="Teddysun <(email protected)>"

COPY --from=builder /root/vlmcsd/bin/vlmcsd /usr/bin/vlmcsd
EXPOSE 1688
CMD ( "vlmcsd", "-D", "-e" )

$TARGETPLATFORM is a built-in variable, represented by --platform parameter to specify its value.
Since it is based on mirror of alpineto make, and alpine It supports the following 7 system architectures, so the images we make also support these 7 system architectures.

linux/amd64, linux/arm/v6, linux/arm/v7, linux/arm64, linux/386, linux/ppc64le, linux/s390x

A more friendly schema name is as follows:

amd64, arm32v6, arm32v7, arm64v8, i386, ppc64le, s390x

Here is a comment interspersed.
After a brief statistics, ARM’s system architecture has the following abbreviations:

arm64, armv8l, arm64v8, aarch64
arm, arm32, arm32v7, armv7, armv7l, armhf
arm32v6, armv6, armv6l, arm32v5, armv5,  armv5l, armel, aarch32

After reading this, do you want to hit someone?
Comparing Intel and AMD is much simpler:

x86, 386, i386, i686
x86_64, x64, amd64

4. Build the image

Let’s build one locally first.

git clone the sample Dockerfile just now and enter its directory

$ cd ~ && git clone https://github.com/teddysun/across.git && cd across/docker/kms/

Build images locally that support 7 platforms

$ docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x,linux/386 -t teddysun/kms -o type=local,dest=.docker -f ./Dockerfile.architecture .

For the specific parameter meanings of docker buildx build, please refer to the official document below
https://docs.docker.com/engine/reference/commandline/buildx_build/

After completing the above step, you actually place the built image in the local path.
At this point let's take a look at the existing builder instances.

$ docker buildx ls
NAME/NODE    DRIVER/ENDPOINT             STATUS  PLATFORMS
mybuilder *  docker-container                    
  mybuilder0 unix:///var/run/docker.sock running linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
default      docker                              
  default    default                     running linux/amd64, linux/386

You will find that there are 8 supported architectures under mybuilder (riscv64 is not currently available, but it is supported).

At this time, check the running status of docker image and you will find that there is a file called buildx_buildkit_mybuilder0 container is running.
This was automatically created when building locally just now. Remember not to stop it or delete it.

$ docker ps -as
CONTAINER ID        IMAGE                           COMMAND           CREATED             STATUS              PORTS             NAMES                        SIZE
be753fa16090        moby/buildkit:buildx-stable-1   "buildkitd"       15 minutes ago      Up 15 minutes                         buildx_buildkit_mybuilder0   0B (virtual 78.6MB)

Then build a multi-system architecture image and push the built image to the Docker warehouse (that is, hub.docker.com)。

Before this operation, you need to register an account in advance (the demonstration process is omitted) and log in.
The login command is as follows:

$ docker login

Enter your username and password to log in.

Note that in the following demonstrated command, the tag is preceded by my user name. teddysunif you want to make your own mirror, please replace it with your own username.
use --push The image built with parameters is pushed to the Docker warehouse.
At this time, it is still in the ~/across/docker/kms directory just now, and the file Dockerfile.architecture It is prepared for multi-system architecture construction.
The command is as follows:

$ docker buildx build --platform linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x -t teddysun/kms --push -f ./Dockerfile.architecture .

After the command is executed successfully, you will see the image you uploaded in Docker Hub. An example diagram is as follows:

5.

When making a Docker image with a multi-system architecture, it is recommended to use a VPS with a strong CPU or multi-core to build it, otherwise it will be very time-consuming.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button