您好,登錄后才能下訂單哦!
buildx中怎么構建多平臺 Docker 鏡像,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
如果你能夠訪問目標 CPU 架構的系統(tǒng),并且該操作系統(tǒng)支持運行構建所需的各種工具,那么你可以直接在目標系統(tǒng)上編譯程序。
以構建 Docker 鏡像為例,你可以在樹莓派上安裝 Docker,然后在樹莓派上通過 Dockerfile
直接構建 arm 平臺的鏡像。
如果無法訪問目標 CPU 架構的系統(tǒng)該怎么辦?有沒有辦法通過某種方式直接在當前系統(tǒng)上構建目標 CPU 架構的程序?請看下文...
還記得我們小時候在各種網(wǎng)吧臺球室之類的場合玩的街機游戲嗎?放張圖給你們回憶一下:
如果現(xiàn)在我們想重新體驗以前玩過的街機游戲該怎么辦?這時候就需要用到模擬器(Emulator)了。借助模擬器,我們可以讓時光倒流,體驗經(jīng)典游戲的樂趣。
模擬器除了可以用來玩游戲之外,還可以用來跨 CPU 架構構建程序。最常用的模擬器是開源的 QEMU,QEMU 支持許多常見的 CPU 架構,包括 ARM
、Power-PC
和 RISC-V
等。通過模擬一個完整的操作系統(tǒng),可以創(chuàng)建通用的 ARM 虛擬機,該虛擬機可以引導 Linux,設置開發(fā)環(huán)境,也可以在虛擬機內(nèi)編譯程序。
然而,模擬整個操作系統(tǒng)還是有點浪費,因為在這種模式下,QEMU 將會模擬整個系統(tǒng),包括計時器、內(nèi)存控制器、總線控制器等硬件。但編譯程序根本不需要關心這些,還可以再精簡些。
在 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 鏡像就比以前容易多了,至于這個插件到底是啥,下文會詳細介紹。
利用 Docker 19.03 引入的插件 buildx,可以很輕松地構建多平臺 Docker 鏡像。buildx 是 docker build ...
命令的下一代替代品,它利用 BuildKit 的全部功能擴展了 docker build
的功能。
下面就來演示一下如何在短短幾分鐘內(nèi)使用 buildx
構建出不同平臺的 Docker 鏡像。步驟如下:
要想使用 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
> 如果你使用的是 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 會通過 QEMU
和 binfmt_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è)資訊頻道,感謝您對億速云的支持。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。