主頁 >  其他 > 多平臺容器鏡像構建就看這一篇

多平臺容器鏡像構建就看這一篇

2020-12-26 06:57:47 其他

前言

愿景與現實

早在1995年,就有“write once and run anywhere”(WORA,撰寫一次即可在任何地方運行)用于描述 Java 應用程式,時過20年,Docker 高聲喊出了自己的口號——“Build Once, Run Anywhere”(一次構建,隨處可用),

愿望是美好的,然而,現實總比理想骨感, Linux、Windows 這些不同的作業系統擁有不同的系統 API; x86、Arm、IBM PowerPC 這些不同的硬體平臺的指令集不同,某些同平臺的硬體甚至擁有不同的專用指令集用于加速應用,一次構建,隨處可用面臨著巨大的挑戰,要構建能夠在不同作業系統、不同硬體平臺的運行的應用程式,仍然需要工程師們針對具體的作業系統和硬體平臺進行海量的移植作業,

Why and How

既然多平臺的支持這么麻煩、充滿挑戰,我們是不是可以放棄支持?然而隨著國產化大潮和 IoT 物聯網的來臨,我們撰寫的應用程式不僅僅會在X86服務器上運行,新時代的工程師們不得不面對更多的硬體平臺,放棄多平臺的支持無疑是放棄更寬廣的未來,多平臺的支持,勢在必行,

我們正處在一個波瀾壯闊的大時代中,新技術、新工具在一次次的迭代升級,不斷從Proposal (提議)到 Prototype(原型),再逐漸的實用化,

虛擬化技術使得我們可以做到模擬其它硬體平臺;Docker 等容器技術打破混亂,讓開發、編譯、運行環境一致化;Golang、Rust 這樣原生支持多系統多平臺的編程語言屏蔽大量底層差異,降低跨平臺應用的開發難度,這一系列前人智慧火花匯聚到一起,發生了奇妙的反應——WORA 真正變的觸手可及,夢想的陽光已經照進現實,

本篇章會大量分析技術原理及實作細節,對于希望快速 GET 可執行方案的同學,可以直接跳轉到【可執行方案回顧】查看,

如何支持多平臺

要了解容器鏡像是如何支持多平臺的,那我們需要仔細聊聊 Manifest,使用過容器技術的同學都知道,我們運行容器所使用的鏡像是由多層構成的,而這些層的清單和其它容器資訊共同存放在 Manifest 當中,

Manifest

我們通常使用的容器鏡像是x86平臺的,執行 docker manifest inspect harbor-community.tencentcloudcr.com/multi-arch/alpine 命令可以查看鏡像 harbor-community.tencentcloudcr.com/multi-arch/alpine 的 Manifest 內容是一個 JSON 物件(如代碼段-01所示),各個欄位的解釋如下:

  1. mediaType 欄位宣告這是一個V2 Manifes,
  2. schemaVersion 版本,
  3. config 鏡像配置資訊,
  4. layers 鏡像層資訊,
// 代碼段-01
{
	"schemaVersion": 2,
	"mediaType": "application/vnd.docker.distribution.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"
		}
	]
}

顯而易見的是,Manifest 當中并沒有任何欄位描述鏡像的平臺資訊,那應該怎么樣支持多平臺呢?

我們可以設想一個簡單粗暴的,無視鏡像的平臺,強行把交叉編譯出來的其它平臺的二進制程式添加到鏡像內,使用 Repository 名稱或者 Tag 名稱來區分不同平臺的鏡像,例如 coredns/coredns:coredns-arm64,在使用的時候,人工或者通過腳本判斷應該拉取那個鏡像,

Schema 2

Ohhhhh,這當然可以跑起來,但是難免太挫了吧?事實上,早在2015年底 Docker 社區的 manifest v2.2 規格檔案(也叫 Schema 2,參見 https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-2.md )中就提及了多平臺鏡像,該功能通過 manifest list(也叫做 fat manifest) 參考多個不同平臺鏡像的 Manifest 實作,

首先讓我們看看 manifest 是什么樣的,執行 docker manifest inspect alpine 命令可以查看Docker Hub 上的多平臺鏡像 alpine 的 Manifest,

// 代碼段-02
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.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"
         }
      }
   ]
}

可以看出來 manifest list 是一個 JSON 陣列,陣列當中應用了不同平臺鏡像的 Manifest,所以,推送多平臺鏡像時,我們需要先分別推送不同平臺的鏡像層;然后創建 manifest list , 再參考平臺鏡像的 Manifest,最后把 manifest list 上傳到 Registry 服務,而拉取鏡像時,客戶端應當設定 HTTP 的請求頭欄位 Accept 值為 application/vnd.docker.distribution.manifest.v2+jsonapplication/vnd.docker.distribution.manifest.list.v2+json,然后檢查服務端回傳的回應頭欄位Content-Type 判斷是舊鏡像格式,新鏡像格式或者時鏡像清單,

拋開規格檔案來說,只要我們使用的 Registry 服務的 Distribution 版本不低于 v2.3,Docker CLI 版本不低于 v1.10 就能過支持多平臺鏡像功能,

構建多平臺鏡像

要構建多平臺的容器鏡像,我們需要確保容器基礎鏡像和應用程式的代碼或者二進制都是目標平臺的,

程式代碼

一些編程語言的編譯器能夠為其它平臺編譯二進制檔案,最為著名的包括 Golang 和 Rust,我們將使用 Golang 撰寫一個演示用 web 程式——通過 HTTP 訪問查看 web 服務程式的作業系統、硬體平臺等資訊,具體代碼如代碼段-03 所示,

// 代碼段-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)
}

我們在 MacOS 上使用 go run 運行代碼段-03, httpie 工具訪問本機:9090 埠,將會看見如下資訊,

enter image description here

代碼準備好了,現在我們有兩種構建方法:手動編譯,使用 docker build 構建鏡像;使用 docker buildx 工具自動化編譯構建,

手動編譯構建

前置條件

  • Dockerd 啟用 experimental

我們需要在 Docker daemon 組態檔中配置 "experimental": true開啟實驗性功能:

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

修改 Docker daemon 配置需要重啟服務使配置生效:

$ sudo systemctl restart docker.service

使用 docker version 命令查看版本資訊,配置生效后可以看到 Server: Docker Engine 中有 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:       go1.13.10
  Git commit:       48a66213fe
  Built:            Mon Jun 22 15:44:07 2020
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
`

如果您使用的 Docker CLI 版本低于 v20.10 ,執行 docker manifest 命令會看到報錯提示 docker manifest is only supported on a Docker cli with experimental cli features enabled ,此時我們需要執行 export DOCKER_CLI_EXPERIMENTAL="enabled" 開啟客戶端實驗特性支持,在 v20.10 及以上版本的 Docker CLI 會默認開啟實驗特性,無需額外操作,

交叉編譯

在我們的 Golang 代碼中沒有使用 CGO 的時候,通過簡單設定環境變數就能夠交叉編譯出其它平臺和作業系統上能夠執行的二進制檔案,其中:

  1. GOARCH 用于指定編譯的目標平臺,如 amd64arm64riscv64 等平臺,
  2. GOOS 用于指定編譯的目標系統,如 darwinlinux

本篇中,我們構建能夠在 Linux 發行版中執行的容器鏡像,所以編譯目標系統環境變數GOOS統一設定為linux,執行代碼段0-4中的命令構建出二進制檔案備用,

// 代碼段-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;
done

構建各個平臺的鏡像

首先,我們撰寫一個 Dockerfile用于構建鏡像,

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

然后,分別構建不同平臺的鏡像,可以使用如代碼段-05的腳本幫助構建,

// 代碼段-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 ;
done

創建 Manifest List

我們使用docker manifest 子命令管理 manifest list,其中,docker manifest create 子命令用于在本地創建一個 manifest list,該命令需要指定待 manifest list 地址和一系列的 manifests,例如需要創建包含amd64arm64 兩個平臺鏡像的 manifest list,則命令如:

docker manifest create kofj/multi-demo kofj/multi-demo:amd64 kofj/multi-demo:arm64

docker manifest create 命令的詳細幫助資訊如下所示:

# 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 registry

我們按照上述方法創建出來的 manifest list 中并沒有說明其中的 manifest 是什么作業系統和平臺的,docker manifest annotate 命令用于注釋創建出來的 manifest list,例如注釋某個 manifest 是 linxu系統 arm64 平臺的,則命令:

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

docker manifest annotate 命令的詳細幫助資訊如下所示:

# 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

注意:

  1. 創建 manifest list 清單的程序中會檢查遠端倉庫中 manifests 是否存在,所以我們必修提前推送鏡像到遠端,如果遠端倉庫是不安全的,在創建的程序中需要添加引數 --inseure
  2. 使用 docker manifest annotate 注釋 manifest list 的時候不需要使用--insecure

為了方便使用,我們可以使用下述代碼段-06 的腳本創建 manifest list,

// 代碼段-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; \
done

推送 manifest list

當我們完成 manifest list 的創建作業后,它還是存盤在本地的,這時候,還需要推送到遠端的鏡像倉庫,與推送普通鏡像不同,推送 manifest list 需要使用 docker manifest push 命令進行,如果我們要推送 kofj/multi-demo 這個 manifest list,則命令如:

docker manifest push kofj/multi-demo

使用 docker manifest push 命令可以通過附加--purge 選項在推送完成后洗掉存盤在本地的 manifest list; 當我們的目標倉庫沒有使用或者使用了非可信 TLS 證書的時候,則需要使用 --insecure 選項,

buildx 自動構建

軟體依賴

  • Docker >= 19.03: 自該 Docker 版本包含 buildx,
  • Linux kernel >= 4.8: 自該Linux內核版本 binfmt_misc 支持 fix-binary (F) flag,fix_binary 標志允許內核在容器或chroot內使用binfmt_misc注冊的二進制格式處理程式,即使該處理程式二進制檔案不是該容器或chroot內可見的檔案系統的一部分,
  • binfmt_misc file system mounted: 需要掛載binfmt_misc檔案系統,以便用戶空間工具可以控制此內核功能,即注冊和啟用處理程式,
  • Docker Desktop >= 2.1.0 如果是使用的 Docker Desktop,
Environment Docker 安裝包 Kernel binfmt-support (F) Flag
需求 >= 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
騰訊云
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
亞馬遜 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 (谷歌 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 (微軟 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

配置 Buildx

buildx 從 19.03 開始與 Docker CE 捆綁發布,但是需要我們在 Docker CLI 上啟用實驗性功能開開啟,可以通過兩種方式啟用它:

  1. "experimental": "enabled” 添加到 Docker CLI 的組態檔 ~/.docker/config.json
  2. 另外一種方法時設定環境變數 DOCKER_CLI_EXPERIMENTAL=enabled

使用 Docker Desktop 的同學可以通過 UI 選單 PreferencesCommand Line 進入 Docker CLI 配置界面,通過Switch 開關 Enable experimental features啟用實驗性功能,

image-20201006100313617.pngenter image description here

如果需要使用最新版本的 buildx,可以從 https://github.com/docker/buildx/releases/latest 下載最新的二進制發行版,并將其復制到~/.docker/cli-plugins檔案夾中,重命名為docker-buildx,然后更改執行權限:

chmod +x ~/.docker/cli-plugins/docker-buildx

最后讓我們驗證 buildx 是否已經可用了:

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

配置 binfmt_misc

QEMU 是一個很棒的開源專案,它可以模擬很多平臺,將 QEMU 和 Docker 結合起來使用能使得我們更容易的構建跨平臺的容器鏡像,集成 QEMU依賴于 Linux 內核功能 ,Linux 內核中的 binfmt_misc功能可以使得內核識別任意型別的可以執行檔案格式,并傳遞到特定的用戶空間應用程式和虛擬機(https://zh.wikipedia.org/wiki/Binfmt_misc),當 Linux 遇到一種無法識別的可執行檔案格式(比如說其它平臺的可執行檔案格式)時,它會檢查有沒有配置任何“用戶空間應用程式”用于處理它,如果檢測到了,就將可執行檔案傳遞給該應用程式,

為此,我們需要在內核當中注冊其它平臺的可執行檔案格式,

對于使用 Docker Desktop(MacOS 和 Windows 上都是)的同學,因為默認配置了 binfmt_misc,可以跳過這一步,而使用 Linux 發行版作業系統的同學則需要自行安裝配置 binfmt_misc,以便能夠非原生的其它平臺的鏡像,

要在宿主機上執行其它 CPU 平臺的指令,需要安裝 QEMU 模擬器,因為程式執行時會在當前程式可見的檔案系統中查找動態庫,而在容器或chroot環境中注冊的處理程式在其它的 cgroup namespace 中可能無法找到,所以需要靜態編譯連接的QEMU,同時,我們需要安裝一個包含足夠新的update-binfmts二進制檔案的包,以便能夠支持fix-binary(F)標志,并在注冊QEMU模擬器時實際使用,這樣才能結合 buildx 一起鏡像跨平臺構建,

QEMU 和 binfmt_misc 支持工具可以通過宿主機或者Docker 容器鏡像安裝,但是,使用Docker鏡像安裝配置能讓事情變得更加簡單,鏡像 docker/binfmt 中包含QEMU二進制檔案和在binfmt_misc中注冊QEMU的安裝腳本,

docker run --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d

執行完后,我們驗證下是否注冊成功了,成功注冊后,/proc/sys/fs/binfmt_misc 目錄中會有多個qemu-前綴的檔案,查看 /proc/sys/fs/binfmt_misc/qemu-aarch64 檔案內容,可以看到 falgs 標志為 OCF,說明這個處理程式是通過 (F)標志注冊的,能夠正常的結合 buildx 完成跨平臺構建,

 ? 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 ffffffffffffff00fffffffffffffffffeffff

使用 buildx 構建

前置依賴注備好后,我們終于可以使用 buildx 構建多平臺鏡像了,與其它方案不同的是,使用 buildx 可以讓我們不必改動 dockerfile,

Buildx 始終使用 BuildKit 引擎構建鏡像,不需要配置環境變數DOCKER_BUILDKIT=1,BuildKit 可以很好的用于多個平臺的構建,而不僅適用于我們當前構建鏡像時所使用的平臺和作業系統,進行構建時,使用 --platform標志可以用于指定構建輸出的目標平臺(例如 linux/amd64linux/arm64,linux/riscv64),

首先,我們先準備好 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"]

然后,讓我們嘗試下運行 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 instance

居然報錯 error: auto-push is currently not implemented for docker driver, please create a new builder instance 了!別擔心,這是因為 Docker 默認的 builder 是不支持多平臺構建的,我們可以通過 docker buildx ls 查看當前節點上的 builder 有哪些,

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

為了使用多平臺構建功能,我們需要新建一個 builder,并設定當前 builder 為新建的,

# 新建同時切換 builder 
docker buildx create --use --name mybuilder
# 只新建,然后再切換 builder
docker buildx create --name mybuilder
docker buildx use mybuilder

現在,讓我們再次執行 buildx,看著一切向著期待的方向發展了,

注意事項

??注意1:到目前位置,buildx支持 linux/amd64, linux/386, linux/arm/v7, linux/arm/v6, linux/arm64, linux/ppc64le, linux/s390x,所以 docker/binfmt 鏡像僅注冊了 arm、ppc64le 和 s390x 的處理程式,如果你需要構建、運行 RISC-V 平臺的容器鏡像,建議使用 multiarch/qemu-user-static 鏡像鏡像配置,

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

??注意2:在 軟體依賴 中我們提到需要 Linux 內核版本 >= 4.8.0;如果在內核版本為 3.10.0 的系統(比如 CentOS)上運行 docker/binfmt,會出現報錯 Cannot write to /proc/sys/fs/binfmt_misc/register: write /proc/sys/fs/binfmt_misc/register: invalid argument,這是由于內核不支持 (F)標志造成的,出現這種情況,建議您升級系統內核或者換使用較高版本內核的 Linux 發行版,

enter image description here

小結

多年前,大規模部署應用程式是一項非常耗費人力、財力、時間,還需要大量技能和技巧的事務,工程師們還需要應對應用程式所運行的每一臺服務器的環境差異,這對大公司而言是個極其沉重的負擔,小公司更是無力應對,

正如多年前人們無法想象大規模部署復雜的應用程式只需要一個 kubectl create 命令,不久前我們也不會想到構建多平臺的容器鏡像只需要一個 docker buildx build,但是,我們還有更加廣闊的想象空間,自動化流程、更多平臺的支持、更智能簡單的工具,你能想到的都有可能在不久的將來變成現實,

技術的發展進步,不斷降低了生產活動中社會平均勞動時間,提升了生產力,能夠釋放勞動者去做更多有益的探索,讓我們不斷學習、擁抱、應用新技術,在時代的浪潮中勇往直前,

可執行方案回顧

  1. 確保使用的 Linux 發行版內核>=4.8.0(推薦使用 Ubuntu 18.04 以上的 TLS 發行版),且 Docker >= 19.03
  2. 啟用Docker CLI 實驗性功能: export DOCKER_CLI_EXPERIMENTAL=enabled
  3. 配置其它平臺的模擬器:docker run --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d
  4. 新建 Docker builder 實體支持多平臺構建: docker buildx create --use --name mybuilder
  5. 在專案目錄中執行構建: docker buildx build --platform linux/amd64,linux/arm64,linux/arm -t harbor-community.tencentcloudcr.com/${YOUR_NAMESPACE}/multi-arch:2020-10-12 . --push
  6. 相關演示代碼、腳本可以在 https://github.com/kofj/multi-arch-demo.git 獲取,

推廣時間

目前,騰訊云容器鏡像服務 TCR已完成公測進入商業化階段,我們也已經對部分用戶開放了 Multi Arch 鏡像和 OCI 云原生制品支持,如果您對該功能感興趣,歡迎聯系客服開通,
mult-arch-tcr-console

【騰訊云原生】云說新品、云研新術、云游新活、云賞資訊,掃碼關注同名公眾號,及時獲取更多干貨!!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/240392.html

標籤:其他

上一篇:淺談 WebRTC 的 Audio 在進入 Encoder 之前的處理流程

下一篇:Tensorflow學習-1

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more