preface

Vision and Reality

As far back as 1995, the term “Write once and run anywhere” (WORA, write once and run anywhere) has been used to describe Java applications. Twenty years later, Docker’s slogan was “Build Once, Run Anywhere.”

Wishes are good, but reality is better than ideal. Different operating systems such as Linux and Windows have different system apis. X86, Arm, IBM PowerPC, and other hardware platforms have different instruction sets. Some of the hardware platforms even have different special instruction sets to speed up applications. It is a huge challenge to build applications that can run on different operating systems and hardware platforms. Engineers still need to carry out massive porting work for specific operating systems and hardware platforms.

Why and How

Since multi-platform support is so cumbersome and challenging, can we give it up? However, with the advent of localization and the Internet of Things, we will write applications to run on more than just X86 servers. Engineers in the new era will have to face more hardware platforms, and abandoning multi-platform support will undoubtedly give up the broader future. Multi-platform support is imperative.

We are living in a magnificent era. New technologies and tools are being upgraded one after another, from Proposal to Prototype, and then gradually put into practice.

Virtualization technology allows us to emulate other hardware platforms; Docker and other container technologies break the chaos, so that the development, compilation, running environment consistent; Programming languages like Golang and Rust that support multiple systems and platforms natively mask a lot of underlying differences and make cross-platform application development easier. This series of predecessors’ wisdom sparks come together, and a wonderful reaction occurs — WORA is truly within reach, and the sunshine of dream has shone into reality.

This chapter will analyze a lot of technical principles and implementation details, for those who want to quickly GET executable solutions, you can directly jump to the “Executable Solutions Review”.

How to support multiple platforms

To understand how container images support multiple platforms, we need to take a closer look at Manifest. Those of you who have used container technology know that the image we use to run containers is made up of several layers, and the lists of these layers are stored in the Manifest along with other container information.

Manifest

The typical container image we use is x86, Perform docker manifest inspect harbor-community.tencentcloudcr.com/multi-arch/alpine command to view images Harbor-community.tencentcloudcr.com/multi-arch/alpine Manifest content is a JSON object (as shown in the code segment – 01). Each field is explained as follows:

  1. mediaTypeThe field declares that this is V2 Manifes.
  2. schemaVersionVersion.
  3. configImage configuration information.
  4. layersMirror layer information.
/ / code - 01 {" schemaVersion ": 2," mediaType ":" application/VND. Docker. Distribution. The manifest. V2 + json ", "config" : { "mediaType": "application/vnd.docker.container.image.v1+json", "size": 1507, "digest": "sha256:f70734b6a266dcb5f44c383274821207885b549b75c8e119404917a61335981a" }, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 2813316, "digest": "sha256:cbdbe7a5bc2a134ca8ec91be58565ec07d037386d1f1d8385412d224deafca08" } ] }Copy the code

Obviously, there are no fields in the Manifest that describe the platform of the image. So how do you support multiple platforms?

We can imagine a crude, unmirrored platform that forces cross-compiled binaries from other platforms to be added to the image, using a Repository name or Tag name to distinguish between platforms, such as coreDNS/CoreDNS: coreDNS-arm64. At the time of use, either manually or through a script, determine which image should be pulled.

Schema 2

Ohhhhh, it works, but it sucks, right? In fact, back in late 2015 the Docker community’s Manifest V2.2 specification document (also called Schema 2, see github.com/docker/dist…) Multi-platform mirroring is mentioned in the manifest List (also known as fat Manifest), which references the manifest of multiple platform mirrors.

Docker Manifest inspect Alpine docker Manifest inspect Alpine docker Manifest inspect

{/ / code - 02 "schemaVersion" : 2, "mediaType" : "application/VND. Docker. Distribution. The manifest. List the v2 + json", "manifests" : [ { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 528, "digest": "sha256:a15790640a6690aa1730c38cf0a440e2aa44aaca9b0e8931a9f2b0d7cc90fd65", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 528, "digest": "sha256:71465c7d45a086a2181ce33bb47f7eaef5c233eace65704da0c5e5454a79cee5", "platform": { "architecture": "arm", "os": "linux", "variant": "v6" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 528, "digest": "sha256:c929c5ca1d3f793bfdd2c6d6d9210e2530f1184c0f488f514f1bb8080bb1e82b", "platform": { "architecture": "arm", "os": "linux", "variant": "v7" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 528, "digest": "sha256:3b3f647d2d99cac772ed64c4791e5d9b750dd5fe0b25db653ec4976f7b72837c", "platform": { "architecture": "arm64", "os": "linux", "variant": "v8" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 528, "digest": "sha256:90baa0922fe90624b05cb5766fa5da4e337921656c2f8e2b13bd3c052a0baac1", "platform": { "architecture": "386", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 528, "digest": "sha256:5d950b30f229f0c53dd7dd7ed6e0e33e89d927b16b8149cc68f59bbe99219cc1", "platform": { "architecture": "ppc64le", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 528, "digest": "sha256:a5426f084c755f4d6c1d1562a2d456aa574a24a61706f6806415627360c06ac0", "platform": { "architecture": "s390x", "os": "linux" } } ] }Copy the code

As you can see, the Manifest list is a JSON array that applies the manifest images of different platforms. Therefore, when pushing multi-platform images, we need to push the mirror layers of different platforms respectively. Then create the manifest list, reference the platform image’s MANIFEST, and upload the manifest list to the Registry service. And when I pull the mirror image, The client should set the HTTP request header field Accept value to Application/VND. Docker. Distribution. The manifest. V2 + json and application/VND. The docker. Distribution. The manifest. The list. The v2 + json, Then check the content-Type header field returned by the server to determine whether it is the old image format, the new image format or the current image list.

Regardless of the specification document, we can support multi-platform mirroring as long as the Distribution version of the Registry service is at least V2.3 and the CLI version of Docker is at least V1.10.

Build multi-platform images

To build multi-platform container images, we need to ensure that both the container base image and the application code or binaries are for the target platform.

The program code

Compilers for several programming languages can compile binaries for other platforms, most notably Golang and Rust. We’ll use Golang to write a demo Web application that looks at the operating system, hardware platform, and so on of the Web service application through HTTP access. The specific code is shown in code segment -03.

Package main import ("net/ HTTP ""runtime" "github.com/gin-gonic/gin") var (r = gin.Default()) func main() { r.GET("/", indexHandler) r.Run(":9090") } func indexHandler(c *gin.Context) { var osinfo = map[string]string{ "arch": runtime.GOARCH, "os": runtime.GOOS, "version": runtime.Version(), } c.JSON(http.StatusOK, osinfo) }Copy the code

Use go Run on MacOS to run code section -03, httpie tool to access local :9090 port, you should see the following information.

Now that the code is ready, we have two ways to build it: manually compile it and build the image using the Docker build; Build automatically using the Docker Buildx tool.

Manual build

precondition

  • Dockerd enabledexperimental

We need to configure “experimental”: true in the Docker Daemon configuration file to enable experimental functionality:

$ vi /etc/docker/daemon.json
{
  "experimental": true
}
Copy the code

To change the Docker Daemon configuration, restart the service:

$ sudo systemctl restart docker.service
Copy the code

Run the docker version command to view the version information. After the configuration takes effect, you can see that Server: Docker Engine has Experimental: true:

$sudo Docker version Client: Docker Engine - Community version: 19.03.12 API Version: 1.40 Go Version: Go1.13.10 Git commit: 48a66213fe Built: Mon Jun 22 15:45:36 2020 OS/Arch: Linux/AMd64 Experimental: false Server Docker Engine - Community Engine: Version: 19.03.12 API Version: 1.40 (minimum Version 1.12) Go Version: Git commit: 48a66213fe Built: Mon Jun 22 15:44:07 2020 OS/Arch: Linux/AMd64 Experimental: true containerd: Version: 1.2.13 GitCommit: 7 ad184331fa3e55e52b890ea95e65ba581ae3429 runc: Version: 1.0.0 - rc10 GitCommit: Dc9208a3303feef5b3839f4323d9beb36df0a9dd docker - init: Version: 0.18.0 GitCommit: fec3683 `Copy the code

If you are using a Docker CLI version earlier than V20.10, Docker manifest is only supported on a docker cli with experimental CLI features enabled In this case, run export DOCKER_CLI_EXPERIMENTAL=”enabled” to enable the client experimental feature. Docker CLI of v20.10 and later will enable the experimental feature by default, no additional operations are required.

cross-compilation

When CGO is not used in our Golang code, it is possible to cross-compile binaries that can be executed on other platforms and operating systems by simply setting environment variables. Among them:

  1. GOARCHUsed to specify the target platform for compilation, such asamd64,arm64,riscv64Such as platform.
  2. GOOSUsed to specify the target system for compilation, such asdarwin,linux.

In this article, we build container images that can be executed in Linux distributions, so the compile target system environment variable GOOS is uniformly set to Linux. Execute the commands in code segments 0-4 to build the binaries for use.

// code snippet -04 #! /bin/bash IMAGE? =kofj/multi-demo NOCOLOR:='\033[0m' RED:='\033[0;31m' GREEN:='\033[0;32m' BUILD_ARCH?=$(uname -m) BUILD_OS?=$(uname -s) BUILD_PATH:=build/docker/linux LINUX_ARCH?=amd64 arm64 riscv64 LDFLAGS:="-s -w -X github.com/kofj/multi-arch-demo/cmd/info.BuildArch=$(BUILD_ARCH) -X github.com/kofj/multi-arch-demo/cmd/info.BuildOS=$(BUILD_OS)" for arch in ${LINUX_ARCH}; do echo ===================; echo ${GREEN}Build binary for ${RED}linux/$$arch${NOCOLOR}; echo ===================; GOARCH=$$arch GOOS=linux go build -o ${BUILD_PATH}/$$arch/webapp -ldflags=${LDFLAGS} -v cmd/main.go; doneCopy the code

Build mirrors of each platform

First, we write a Dockerfile to build the image.

FROM scratch
LABEL authors="Fanjian Kong"
ADD webapp /app/
WORKDIR /app
CMD ["/app/webapp"]
Copy the code

Then, build the images for each platform, using scripts like snippet -05 to help build.

// code snippet -05 #! /bin/bash IMAGE? =kofj/multi-demo NOCOLOR:='\033[0m' RED:='\033[0;31m' GREEN:='\033[0;32m' LINUX_ARCH?=amd64 arm64 riscv64 BUILD_PATH:=build/docker/linux for arch in ${LINUX_ARCH}; do echo =================== ; echo ${GREEN}Build docker image for ${RED}linux/$$arch${NOCOLOR} ; echo =================== ; cp Dockerfile.slim ${BUILD_PATH}/$$arch/Dockerfile ; docker build -t ${IMAGE}:$$arch ${BUILD_PATH}/$$arch ; doneCopy the code

Create the Manifest the List

We manage the manifest list using the Docker manifest subcommand. The docker manifest create subcommand is used to create a manifest list locally. The command needs to specify the manifest list address and a list of manifests. For example, to create a manifest list that contains both amd64 and ARM64 platform images, run the following command:

docker manifest create kofj/multi-demo kofj/multi-demo:amd64 kofj/multi-demo:arm64
Copy the code

The detailed help information for the docker manifest create command is as follows:

# docker manifest create --help Usage: docker manifest create MANIFEST_LIST MANIFEST [MANIFEST...]  Create a local manifest list for annotating and pushing to a registry Options: -a, --amend Amend an existing manifest list --insecure Allow communication with an insecure registryCopy the code

The manifest list created in accordance with the above method does not specify the operating system and platform of the manifest. The docker manifest annotate command is used to annotate the created manifest list. For example, to annotate a manifest for the LINxu arm64 platform, run the following command:

docker manifest annotate kofj/multi-demo kofj/multi-demo:arm64 --os linux --arch arm64
Copy the code

The help information of the docker manifest annotate command is as follows:

# docker manifest annotate --help
Usage:	docker manifest annotate [OPTIONS] MANIFEST_LIST MANIFEST
Add additional information to a local image manifest
Options:
      --arch string           Set architecture
      --os string             Set operating system
      --os-features strings   Set operating system feature
      --variant string        Set architecture variant
Copy the code

Note:

  1. When creating the manifest, we check for the presence of the manifests in the remote warehouse, so we must push the image to the remote end in advance. If the remote repository is insecure, parameters need to be added during the creation process--inseure.
  2. usedocker manifest annotateThis is not needed when annotating the manifest list--insecure.

For ease of use, we can create the manifest list using the script in code snippet -06 below.

// code snippet -06 #! /bin/bash IMAGE? =kofj/multi-demo NOCOLOR:='\033[0m' RED:='\033[0;31m' GREEN:='\033[0;32m' LINUX_ARCH?=amd64 arm64 riscv64 IMAGES=$(foreach arch,$(LINUX_ARCH),$(IMAGE):$(arch)) @echo ${GREEN}Create manifest for ${RED} \( ${LINUX_ARCH}\) ${NOCOLOR}; @docker manifest create ${IMAGE} ${IMAGES} @for arch in ${LINUX_ARCH}; do \ echo ${GREEN}Annotate manifest ${RED}linux/$$arch${NOCOLOR}; \ echo ===================; \ docker manifest annotate ${IMAGE} ${IMAGE}:$$arch --os linux  --arch $$arch; \ doneCopy the code

Push the manifest the list

When we’re done creating the manifest list, it’s still stored locally. In this case, it also needs to be pushed to the remote mirror warehouse. Different from pushing ordinary images, the manifest list needs to be pushed using the Docker manifest push command. If we want to push the manifest list of kofj/multi-demo, we can run the following command:

docker manifest push kofj/multi-demo
Copy the code

Use the Docker manifest push command to delete the locally stored manifest list after the push is complete by adding the –purge option; We need to use the –insecure option when our target repository doesn’t use or uses untrusted TLS certificates.

Buildx builds automatically

Software depend on

  • Docker >= 19.03: Buildx included since this Docker version.
  • Linux kernel >= 4.8: Since the Linux kernel version binfmt_misc supports fix-binary (F) flag. The Fix_binary flag allows the kernel to use a bINFmT_misc registered binary format handler within a container or chroot, even if the handler binary is not part of the file system visible within that container or chroot.
  • Binfmt_misc File System Mounted: The binfmt_misc file system needs to be mounted so that the user-space tool can control the kernel function, that is, register and enable handlers.
  • Docker Desktop >= 2.1.0 If the Docker Desktop is used.
Environment Docker installation package Kernel binfmt-support (F) Flag
demand > = 19.03 > = 4.8 > = 2.1.7 yes
Ubuntu:
18.04 (bionic) 17.12.1 docker. IO 4.15.0 2.1.8 yes
19.04 (disco) 18.09.5 docker. IO 5.0 2.2.0 yes
19.10 (eoan) 19.03.2 docker. IO 5.3 2.2.0 yes
20.04 (focal) 19.03.2 docker. IO 5.5 2.2.0 yes
Debian:
9 (stretch) 4.9.0 2.1.6 no
10 (buster) 18.09.1 docker. IO 4.19.0 2.2.0 yes
11 (bullseye/testing) 19.03.4 docker. IO 5.4 2.2.0 yes
Tencent cloud
Ubuntu 16.04 (xenial) 18.09.7 docker. IO 4.4.0 2.1.6-1 no
Ubuntu 18.04 (bionic) 19.03.6 docker. IO 4.15.0 2.1.8-2 yes
Amazon EC2:
Ubuntu 16.04 (xenial) 18.09.7 docker. IO 4.4.0 2.1.6 no
Ubuntu 18.04 (bionic) 18.09.7 docker. IO 4.15.0 2.1.8 yes
Travis (Google GCP):
Ubuntu 14.04 (trusty) 17.09.0 docker – ce 4.4.0 2.1.4 no
Ubuntu 16.04 (xenial) 18.06.0 docker – ce 4.15.0 2.1.6 no
Ubuntu 18.04 (bionic) 18.06.0 docker – ce 4.15.0 2.1.8 yes
Github Actions (Microsoft Azure)
Ubuntu 16.04 (xenial) 3.0.8 moby – engine 4.15.0 2.1.6 no
Ubuntu 18.04 (bionic) 3.0.8 moby – engine 5.0.0 2.1.8 yes

Configuration Buildx

Buildx is bundled with Docker CE since 19.03, but requires us to enable experimental function on Docker CLI. It can be enabled in two ways:

  1. will"Experimental" : "enabled"Add the configuration file to the Docker CLI~/.docker/config.json.
  2. The other way is to set the environment variableDOCKER_CLI_EXPERIMENTAL=enabled.

Docker Desktop students can enter the Docker CLI configuration interface through UI menu Preferences → Command Line, Enable experimental features Enable experimental features.

image-20201006100313617.png

To use the latest version of Buildx, you can download it from github.com/docker/buil… Download the latest binary distribution and copy it to the ~/.docker/cli-plugins folder, rename it to docker-buildx and then change execution permissions:

chmod +x ~/.docker/cli-plugins/docker-buildx
Copy the code

Finally, let’s verify that Buildx is already available:

$docker buildx version github.com/docker/buildx v0.3.1 - tp - 6 db68d029599c6710a32aa7adcba8e5a344795a7 dockerCopy the code

Configuration binfmt_misc

QEMU is a great open source project that emulates many platforms. Using QEMU and Docker together makes it easier to build cross-platform container images. Integrated QEMU relies on Linux kernel functionality. Binfmt_misc in the Linux kernel function can make any type of file format that can be performed on the kernel recognition, and pass to a specific user space applications, and virtual machine (zh.wikipedia.org/wiki/Binfmt… When Linux encounters an executable format that it does not recognize, such as that of another platform, it checks to see if any “user-space applications” are configured to handle it. If detected, the executable is passed to the application.

To do this, we need to register executable file formats for other platforms in the kernel.

For those using Docker Desktop (both On MacOS and Windows), you can skip this step because binfmT_misc is configured by default. Those using Linux distributions will need to install and configure bINFMT_MISc to be able to use non-native images from other platforms.

To execute instructions from other CPU platforms on the host, you need to install the QEMU emulator. Because program execution looks for dynamic libraries in the file system visible to the current program, handlers registered in the container or chroot environment may not be found in other CGroup namespaces, you need to statically compile the connected QEMU. Also, we need to install a package that contains enough new Update-Binfmts binaries to be able to support the Fix-Binary (F) flag and actually use it when registering QEMU emulators to mirror cross-platform builds with Buildx.

QEMU and binfmT_MISc support tools can be installed from host or Docker container images. However, using the Docker image to install the configuration makes things much easier. The image docker/binfmt contains the QEMU binary and the installation script that registers QEMU in binfmt_misc.

docker run --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d
Copy the code

After executing, we verify whether the registration is successful. After successful registration, the /proc/sys/fs/binfmt_misc directory will have multiple files with the qemu- prefix. In /proc/sys/fs/binfmt_misc/qemu-aarch64, falgs is marked as OCF, indicating that this handler is registered with (F) flag, and can complete cross-platform building with buildx normally.

⚡ root@kofj-hk ~ ls -al /proc/sys/fs/binfmt_misc total 0 drwxr-xr-x 2 root root 0 Oct 12 20:19.dr -xr-xr-x 1 root root 0 Oct 12 20:19 .. -rw-r--r-- 1 root root 0 Oct 12 20:19 python2.7 -RW-r --r-- 1 root root 0 Oct 12 20:19 python3.6 -RW-r --r-- 1 root root 0  Oct 12 20:21 qemu-aarch64 -rw-r--r-- 1 root root 0 Oct 12 20:21 qemu-arm -rw-r--r-- 1 root root 0 Oct 12 20:21 qemu-ppc64le -rw-r--r-- 1 root root 0 Oct 12 20:21 qemu-s390x --w------- 1 root root 0 Oct 12 20:19 register -rw-r--r-- 1 root root 0 Oct 12 20:19 status ⚡ root@kofj-hk ~ cat /proc/sys/fs/binfmt_misc/qemu-aarch64 enabled Interpreter /usr/bin/qemu-aarch64 flags: OCF offset 0 magic 7f454c460201010000000000000000000200b7 mask ffffffffffffff00fffffffffffffffffeffffCopy the code

Build using Buildx

With the front dependency notes in place, we can finally use Buildx to build multi-platform images. Unlike the other solutions, using Buildx allows us to keep the Dockerfile unchanged.

Buildx always builds images using the BuildKit engine and does not need to configure the environment variable DOCKER_BUILDKIT=1. BuildKit works well for building on multiple platforms, not just the platforms and operating systems we’re currently building our images on. – to build, use the platform flag can be used to specify the build output target platform (such as Linux/amd64, Linux/arm64, Linux/riscv64).

First, let’s prepare the Dockerfile:

FROM golang:1.14 as Builder COPY. / SRC WORKDIR/SRC RUN ls -al && go build -a -tags netgo-ldflags '-w' -mod= vendor-v -o/SRC /bin/webapp/SRC/CMD /main.go # Final image FROM Ubuntu :18.04 LABEL authors="Fanjian Kong" COPY -- FROM =builder /src/bin/webapp /app/ WORKDIR /app CMD ["/app/webapp"]Copy the code

Then, let’s try running Buildx.

✘ ⚡ root @ kofj - hk ~ docker buildx build - platform Linux/amd64, Linux/arm64, Linux/arm - t harbor-community.tencentcloudcr.com/multi-arch/demo:2020-10-12 . --push error: auto-push is currently not implemented for docker driver, please create a new builder instanceCopy the code

Auto-push is currently not implemented for Docker driver, please create a new Builder instance. Don’t worry, this is because Docker’s default Builder doesn’t support multi-platform builds. We can use Docker BuildX ls to see what Builders are on the current node.

 ⚡ root@kofj-hk ~ docker buildx  ls
NAME/NODE DRIVER/ENDPOINT STATUS  PLATFORMS
default * docker
  default default         running linux/amd64, linux/386
Copy the code

To use the multi-platform build feature, we need to create a new Builder and set the current Builder to new.

Docker buildx create --use --name myBuilder Docker Buildx create --name myBuilder docker Buildx use myBuilderCopy the code

Now, let’s execute Buildx again and watch everything go the way we want it to.

Matters needing attention

⚠️ Note 1: Up to now, Buildx supports Linux/AMD64, Linux /386, Linux/ARM/V7, Linux/ARM /v6, Linux/ARM64, Linux/ppC64LE, Linux /s390x. So docker/ Binfmt images only register arm, PPC64LE and S390X handlers. If you need to build and run risC-V container images, it is recommended to use multiarch/qemu-user-static image configuration.

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
Copy the code

⚠️ Note 2: In software dependencies we mention that Linux kernel version is required >= 4.8.0; Cannot write to /proc/sys/fs/binfmt_misc/register: /proc/sys/fs/binfmt_misc/register Write /proc/sys/fs/binfmt_misc/register: invalid argument because the kernel does not support the (F) flag. In this case, it is recommended that you upgrade your system kernel or switch to a Linux distribution with a higher kernel.

summary

Years ago, deploying applications on a large scale was a labor-intensive, financial, time consuming, skill and skill business, and engineers had to deal with the differences in the environment of each server on which the application was running. This is an extremely heavy burden for large companies, and one that small companies cannot cope with.

Just as years ago it was unthinkable to deploy complex applications on a large scale with a kubectl create command, not so long ago it was unthinkable to build multiplatform container images with a Docker Buildx build. But there’s a lot more to think about. Automated processes, more platforms, smarter and simpler tools — you can think of anything that could happen in the near future.

The development and progress of technology has continuously reduced the average labor time in production activities, improved productivity, and freed workers to do more useful exploration. Let us continue to learn, embrace, apply new technology, in the tide of The Times forward.

Review of executable programmes

  1. Ensure that the Linux distribution kernel >=4.8.0 (Ubuntu 18.04 + TLS distribution is recommended) and Docker >= 19.03;
  2. Enable Docker CLI experimental features:export DOCKER_CLI_EXPERIMENTAL=enabled;
  3. Configure emulators for other platforms:docker run --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d;
  4. Docker Builder instance support multi-platform build:docker buildx create --use --name mybuilder;
  5. Perform the build in the project directory:docker buildx build --platform linux/amd64,linux/arm64,linux/arm -t harbor-community.tencentcloudcr.com/${YOUR_NAMESPACE}/multi-arch:2020-10-12 . --push.
  6. Demo codes and scripts can be found at github.com/kofj/multi-… To obtain.

Promotion time

At present, Tencent cloudContainer mirroring service TCRIt has completed the public test and entered the commercial stage. We have also opened Multi Arch images and OCI cloud native support to some users. If you are interested in this function, please contact customer service.