溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

buildx中怎么構建多平臺 Docker 鏡像

發(fā)布時間:2021-07-30 17:01:41 來源:億速云 閱讀:218 作者:Leah 欄目:云計算

buildx中怎么構建多平臺 Docker 鏡像,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

方法一:直接在目標硬件上編譯

如果你能夠訪問目標 CPU 架構的系統(tǒng),并且該操作系統(tǒng)支持運行構建所需的各種工具,那么你可以直接在目標系統(tǒng)上編譯程序。

以構建 Docker 鏡像為例,你可以在樹莓派上安裝 Docker,然后在樹莓派上通過 Dockerfile 直接構建 arm 平臺的鏡像。

如果無法訪問目標 CPU 架構的系統(tǒng)該怎么辦?有沒有辦法通過某種方式直接在當前系統(tǒng)上構建目標 CPU 架構的程序?請看下文...

方法二:模擬目標硬件

還記得我們小時候在各種網(wǎng)吧臺球室之類的場合玩的街機游戲嗎?放張圖給你們回憶一下:

buildx中怎么構建多平臺 Docker 鏡像

如果現(xiàn)在我們想重新體驗以前玩過的街機游戲該怎么辦?這時候就需要用到模擬器(Emulator)了。借助模擬器,我們可以讓時光倒流,體驗經(jīng)典游戲的樂趣。

模擬器除了可以用來玩游戲之外,還可以用來跨 CPU 架構構建程序。最常用的模擬器是開源的 QEMU,QEMU 支持許多常見的 CPU 架構,包括 ARM、Power-PCRISC-V 等。通過模擬一個完整的操作系統(tǒng),可以創(chuàng)建通用的 ARM 虛擬機,該虛擬機可以引導 Linux,設置開發(fā)環(huán)境,也可以在虛擬機內(nèi)編譯程序。

然而,模擬整個操作系統(tǒng)還是有點浪費,因為在這種模式下,QEMU 將會模擬整個系統(tǒng),包括計時器、內(nèi)存控制器、總線控制器等硬件。但編譯程序根本不需要關心這些,還可以再精簡些。

方法三:通過 binfmt_misc 模擬目標硬件的用戶空間

在 Linux 上,QEMU 除了可以模擬完整的操作系統(tǒng)之外,還有另外一種模式叫用戶態(tài)模式(User mod)。該模式下 QEMU 將通過 binfmt_misc 在 Linux 內(nèi)核中注冊一個二進制轉(zhuǎn)換處理程序,并在程序運行時動態(tài)翻譯二進制文件,根據(jù)需要將系統(tǒng)調(diào)用從目標 CPU 架構轉(zhuǎn)換為當前系統(tǒng)的 CPU 架構。最終的效果看起來就像在本地運行目標 CPU 架構的二進制文件。

通過 QEMU 的用戶態(tài)模式,我們可以創(chuàng)建輕量級的虛擬機(chroot 或容器),然后在虛擬機系統(tǒng)中編譯程序,和本地編譯一樣簡單輕松。后面我們就會看到,跨平臺構建 Docker 鏡像用的就是這個方法。

方法四:使用交叉編譯器

最后介紹一種嵌入式系統(tǒng)社區(qū)常用的方法:交叉編譯(cross-compilation)。

交叉編譯器是專門為在給定的系統(tǒng)平臺上運行而設計的編譯器,但是可以編譯出另一個系統(tǒng)平臺的可執(zhí)行文件。例如,amd64 架構的 Linux 系統(tǒng)上的 C++ 交叉編譯器可以編譯出運行在 aarch74(64-bit ARM) 架構的嵌入式設備上的可執(zhí)行文件。再舉個真實的例子,安卓設備的 APP 基本上都是通過這種方法來編譯的。

從性能角度來看,該方法與方法一沒什么區(qū)別,因為不需要模擬器的參與,幾乎沒有性能損耗。但交叉編譯不具有通用性,它的復雜度取決于程序使用的語言,如果使用 Golang 的話,那就超級容易了。

在全民容器時代,我們討論構建時不僅包括構建單個可執(zhí)行文件,還包括構建容器鏡像。而且構建容器鏡像比上面說的方法更復雜,再加上 Docker 本身的復雜性,這幾乎是一個老大難的問題。

但引入了新的實驗性插件之后,構建多平臺架構的 Docker 鏡像就比以前容易多了,至于這個插件到底是啥,下文會詳細介紹。

2. 構建多平臺 Docker 鏡像

利用 Docker 19.03 引入的插件 buildx,可以很輕松地構建多平臺 Docker 鏡像。buildx 是 docker build ... 命令的下一代替代品,它利用 BuildKit 的全部功能擴展了 docker build 的功能。

下面就來演示一下如何在短短幾分鐘內(nèi)使用 buildx 構建出不同平臺的 Docker 鏡像。步驟如下:

啟用 buildx 插件

要想使用 buildx,首先要確保 Docker 版本不低于 19.03,同時還要通過設置環(huán)境變量 DOCKER_CLI_EXPERIMENTAL 來啟用??梢酝ㄟ^下面的命令來為當前終端啟用 buildx 插件:

????  → export DOCKER_CLI_EXPERIMENTAL=enabled

驗證是否開啟:

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

如果在某些系統(tǒng)上設置環(huán)境變量 DOCKER_CLI_EXPERIMENTAL 不生效(比如 Arch Linux),你可以選擇從源代碼編譯:

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

啟用 binfmt_misc

> 如果你使用的是 Docker 桌面版(MacOS 和 Windows),默認已經(jīng)啟用了 binfmt_misc,可以跳過這一步。

如果你使用的是 Linux,需要手動啟用 binfmt_misc。大多數(shù) Linux 發(fā)行版都很容易啟用,不過還有一個更容易的辦法,直接運行一個特權容器,容器里面寫好了設置腳本:

???? → docker run --rm --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d

> 建議將 Linux 內(nèi)核版本升級到 4.x 以上,特別是 CentOS 用戶,你可能會遇到錯誤。

驗證是 binfmt_misc 否開啟:

???? → ls -al /proc/sys/fs/binfmt_misc/
總用量 0
總用量 0
-rw-r--r-- 1 root root 0 11月 18 00:12 qemu-aarch74
-rw-r--r-- 1 root root 0 11月 18 00:12 qemu-arm
-rw-r--r-- 1 root root 0 11月 18 00:12 qemu-ppc64le
-rw-r--r-- 1 root root 0 11月 18 00:12 qemu-s390x
--w------- 1 root root 0 11月 18 00:09 register
-rw-r--r-- 1 root root 0 11月 18 00:12 status

驗證是否啟用了相應的處理器:

???? → cat /proc/sys/fs/binfmt_misc/qemu-aarch74
enabled
interpreter /usr/bin/qemu-aarch74
flags: OCF
offset 0
magic 7f454c460201010000000000000000000200b7
mask ffffffffffffff00fffffffffffffffffeffff

從默認的構建器切換到多平臺構建器

Docker 默認會使用不支持多 CPU 架構的構建器,我們需要手動切換。

先創(chuàng)建一個新的構建器:

???? → docker buildx create --use --name mybuilder

啟動構建器:

???? → docker buildx inspect mybuilder --bootstrap

[+] Building 5.0s (1/1) FINISHED
 => [internal] booting buildkit                                                                                                                          5.0s
 => => pulling image moby/buildkit:buildx-stable-1                                                                                                       4.4s
 => => creating container buildx_buildkit_mybuilder0                                                                                                     0.6s
Name:   mybuilder
Driver: docker-container

Nodes:
Name:      mybuilder0
Endpoint:  unix:///var/run/docker.sock
Status:    running
Platforms: linux/amd64, linux/arm64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

查看當前使用的構建器及構建器支持的 CPU 架構,可以看到支持很多 CPU 架構:

???? → docker buildx ls

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

構建多平臺鏡像

現(xiàn)在我們就可以構建支持多 CPU 架構的鏡像了!假設有一個簡單的 golang 程序源碼:

???? → cat hello.go
package main

import (
        "fmt"
        "runtime"
)

func main() {
        fmt.Printf("Hello, %s!\n", runtime.GOARCH)
}

創(chuàng)建一個 Dockerfile 將該應用容器化:

???? → cat Dockerfile
FROM golang:alpine AS builder
RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN go build -o hello .

FROM alpine
RUN mkdir /app
WORKDIR /app
COPY --from=builder /app/hello .
CMD ["./hello"]

這是一個多階段構建 Dockerfile,使用 Go 編譯器來構建應用,并將構建好的二進制文件拷貝到 alpine 鏡像中。

現(xiàn)在就可以使用 buildx 構建一個支持 arm、arm64 和 amd64 多架構的 Docker 鏡像了,同時將其推送到 Docker Hub:

???? → docker buildx build -t yangchuansheng/hello-arch --platform=linux/arm,linux/arm64,linux/amd64 . --push

> 需要提前通過 docker login 命令登錄認證 Docker Hub。

現(xiàn)在就可以通過 docker pull mirailabs/hello-arch 拉取剛剛創(chuàng)建的鏡像了,Docker 將會根據(jù)你的 CPU 架構拉取匹配的鏡像。

背后的原理也很簡單,之前已經(jīng)提到過了,buildx 會通過 QEMUbinfmt_misc 分別為 3 個不同的 CPU 架構(arm,arm64 和 amd64)構建 3 個不同的鏡像。構建完成后,就會創(chuàng)建一個 manifest list,其中包含了指向這 3 個鏡像的指針。

如果想將構建好的鏡像保存在本地,可以將 type 指定為 docker,但必須分別為不同的 CPU 架構構建不同的鏡像,不能合并成一個鏡像,即:

???? → docker buildx build -t yangchuansheng/hello-arch --platform=linux/arm -o type=docker .
???? → docker buildx build -t yangchuansheng/hello-arch --platform=linux/arm64 -o type=docker .
???? → docker buildx build -t yangchuansheng/hello-arch --platform=linux/amd64 -o type=docker .

測試多平臺鏡像

由于之前已經(jīng)啟用了 binfmt_misc,現(xiàn)在我們就可以運行任何 CPU 架構的 Docker 鏡像了,因此可以在本地系統(tǒng)上測試之前生成的 3 個鏡像是否有問題。

首先列出每個鏡像的 digests

???? → docker buildx imagetools inspect yangchuansheng/hello-arch

Name:      docker.io/yangchuansheng/hello-arch:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest:    sha256:ec55f5ece9a12db0c6c367acda8fd1214f50ee502902f97b72f7bff268ebc35a

Manifests:
  Name:      docker.io/yangchuansheng/hello-arch:latest@sha256:38e083870044cfde7f23a2eec91e307ec645282e76fd0356a29b32122b11c639
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm/v7

  Name:      docker.io/yangchuansheng/hello-arch:latest@sha256:de273a2a3ce92a5dc1e6f2d796bb85a81fe1a61f82c4caaf08efed9cf05af66d
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm64

  Name:      docker.io/yangchuansheng/hello-arch:latest@sha256:8b735708d7d30e9cd6eb993449b1047b7229e53fbcebe940217cb36194e9e3a2
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/amd64

運行每一個鏡像并觀察輸出結果:

???? → docker run --rm docker.io/yangchuansheng/hello-arch:latest@sha256:38e083870044cfde7f23a2eec91e307ec645282e76fd0356a29b32122b11c639
Hello, arm!

???? → docker run --rm docker.io/yangchuansheng/hello-arch:latest@sha256:de273a2a3ce92a5dc1e6f2d796bb85a81fe1a61f82c4caaf08efed9cf05af66d
Hello, arm64!

???? → docker run --rm docker.io/yangchuansheng/hello-arch:latest@sha256:8b735708d7d30e9cd6eb993449b1047b7229e53fbcebe940217cb36194e9e3a2
Hello, amd64!

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI