国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

使用 docker buildx 構(gòu)建跨平臺鏡像 (QEMU/buildx/build)

這篇具有很好參考價值的文章主要介紹了使用 docker buildx 構(gòu)建跨平臺鏡像 (QEMU/buildx/build)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

https://docs.docker.com/build/building/multi-platform

1. 使用 buildx 構(gòu)建跨平臺鏡像

構(gòu)建跨平臺鏡像是 Docker 生態(tài)系統(tǒng)中的一個重要話題, 因為跨平臺鏡像可以在多種平臺上運(yùn)行, 極具靈活性。為了實現(xiàn)這個目標(biāo), Docker 社區(qū)提供了多種方式來構(gòu)建跨平臺鏡像, 其中之一是使用 docker manifest, 我在《使用 docker manifest 構(gòu)建跨平臺鏡像》一文中詳細(xì)介紹了這種方法。然而, 目前最流行的方式是使用 Docker 的 buildx 工具, 這種方式不僅可以輕松構(gòu)建跨平臺鏡像, 還可以自動化整個構(gòu)建過程, 大大提高了效率。在本文中, 我們將重點介紹使用 buildx 構(gòu)建跨平臺鏡像的方法和技巧。

1.1. 簡介

buildx 是 Docker 官方提供的一個構(gòu)建工具, 它可以幫助用戶快速、高效地構(gòu)建 Docker 鏡像, 并支持多種平臺的構(gòu)建。使用 buildx, 用戶可以在單個命令中構(gòu)建多種架構(gòu)的鏡像, 例如 x86 和 ARM 架構(gòu), 而無需手動操作多個構(gòu)建命令。此外, buildx 還支持 Dockerfile 的多階段構(gòu)建和緩存, 這可以大大提高鏡像構(gòu)建的效率和速度。

1.2. 安裝

buildx 是一個管理 Docker 構(gòu)建的 CLI 插件, 底層使用 BuildKit 擴(kuò)展了 Docker 構(gòu)建功能。

筆記: BuildKit 是 Docker 官方提供的一個高性能構(gòu)建引擎, 可以用來替代 Docker 原有的構(gòu)建引擎。相比于原有引擎, BuildKit 具有更快的構(gòu)建速度、更高的并行性、更少的資源占用和更好的安全性。

要安裝并使用 buildx, 需要 Docker Engine 版本號大于等于 19.03。

如果你使用的是 Docker Desktop, 則默認(rèn)安裝了 buildx。可以使用 docker buildx version 命令查看安裝版本, 得到以下類似輸出, 證明已經(jīng)安裝過了。

$ docker buildx version
github.com/docker/buildx v0.9.1 ed00243a0ce2a0aee75311b06e32d33b44729689

如果需要手動安裝, 可以從 GitHub 發(fā)布頁面下載對應(yīng)平臺的最新二進(jìn)制文件, 重命名為 docker-buildx, 然后將其放到 Docker 插件目錄下(Linux/Mac 系統(tǒng)為 $HOME/.docker/cli-plugins, Windows 系統(tǒng)為 %USERPROFILE%.docker\cli-plugins)。

Linux/Mac 系統(tǒng)還需要給插件增加可執(zhí)行權(quán)限 chmod +x ~/.docker/cli-plugins/docker-buildx, 之后就可以使用 buildx 了。

更詳細(xì)的安裝過程可以參考官方文檔。

1.3. 構(gòu)建跨平臺鏡像

首先, 需要澄清的是, 本文中所提到的「跨平臺鏡像」這一說法并不十分準(zhǔn)確。實際上, Docker 官方術(shù)語叫 Multi-platform images 即「多平臺鏡像」, 意思是支持多種不同 CPU 架構(gòu)的鏡像。之所以使用「跨平臺鏡像」這一術(shù)語, 是因為從使用者的角度來看, 在使用如 docker pull、docker run 等命令來拉取和啟動容器時, 并不會感知到這個鏡像是一個虛擬的 manifest list 鏡像還是針對當(dāng)前平臺的鏡像。

筆記: manifest list 是通過指定多個鏡像名稱創(chuàng)建的鏡像列表, 是一個虛擬鏡像, 它包含了多個不同平臺的鏡像信息??梢韵衿胀ㄧR像一樣使用 docker pull 和 docker run 等命令來操作它。如果你想了解關(guān)于 manifest list 的更多信息, 可參考《使用 docker manifest 構(gòu)建跨平臺鏡像》一文。

1.4. 跨平臺鏡像構(gòu)建策略

builder 支持三種不同策略構(gòu)建跨平臺鏡像:

1.4.1. 在內(nèi)核中使用 QEMU 仿真支持

如果你正在使用 Docker Desktop, 則已經(jīng)支持了 QEMU, QEMU 是最簡單的構(gòu)建跨平臺鏡像策略。它不需要對原有的 Dockerfile 進(jìn)行任何更改, BuildKit 會通過 binfmt_misc 這一 Linux 內(nèi)核功能實現(xiàn)跨平臺程序的執(zhí)行。

工作原理:

QEMU 是一個處理器模擬器, 可以模擬不同的 CPU 架構(gòu), 我們可以把它理解為是另一種形式的虛擬機(jī)。在 buildx 中, QEMU 用于在構(gòu)建過程中執(zhí)行非本地架構(gòu)的二進(jìn)制文件。例如, 在 x86 主機(jī)上構(gòu)建一個 ARM 鏡像時, QEMU 可以模擬 ARM 環(huán)境并運(yùn)行 ARM 二進(jìn)制文件。

binfmt_misc 是 Linux 內(nèi)核的一個模塊, 它允許用戶注冊可執(zhí)行文件格式和相應(yīng)的解釋器。當(dāng)內(nèi)核遇到未知格式的可執(zhí)行文件時, 會使用 binfmt_misc 查找與該文件格式關(guān)聯(lián)的解釋器(在這種情況下是 QEMU)并運(yùn)行文件。

QEMU 和 binfmt_misc 的結(jié)合使得通過 buildx 跨平臺構(gòu)建成為可能。這樣我們就可以在一個架構(gòu)的主機(jī)上構(gòu)建針對其他架構(gòu)的 Docker 鏡像, 而無需擁有實際的目標(biāo)硬件。

雖然 Docker Desktop 預(yù)配置了 binfmt_misc 對其他平臺的支持, 但對于其他版本 Docker, 你可能需要使用 tonistiigi/binfmt 鏡像啟動一個特權(quán)容器來進(jìn)行支持:

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

1.4.2. 使用相同的構(gòu)建器實例在多個本機(jī)節(jié)點上構(gòu)建。

此方法直接在對應(yīng)平臺的硬件上構(gòu)建鏡像, 所以需要準(zhǔn)備各個平臺的主機(jī)。因為此方法門檻比較高, 所以并不常使用。

1.4.3. 使用 Dockerfile 中的多階段構(gòu)建, 交叉編譯到不同的平臺架構(gòu)中。

交叉編譯的復(fù)雜度不在于 Docker, 而是取決于程序本身。比如 Go 程序就很容易實現(xiàn)交叉編譯, 只需要在使用 go build 構(gòu)建程序時指定 GOOS、GOARCH 兩個環(huán)境變量即可實現(xiàn)。

1.5. 創(chuàng)建 builder

要使用 buildx 構(gòu)建跨平臺鏡像, 我們需要先創(chuàng)建一個 builder, 可以翻譯為「構(gòu)建器」。

使用 docker buildx ls 命令可以查看 builder 列表:

$ docker buildx ls
NAME/NODE       DRIVER/ENDPOINT STATUS  BUILDKIT PLATFORMS
default *       docker
  default       default         running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
desktop-linux   docker
  desktop-linux desktop-linux   running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

這兩個是默認(rèn) builder, default * 中的 * 表示當(dāng)前正在使用的 builder, 當(dāng)我們運(yùn)行 docker build 命令時就是在使用此 builder 構(gòu)建鏡像。

可以發(fā)現(xiàn), 這兩個默認(rèn)的 builder 第二列 DRIVER/ENDPOINT 項的值都是 docker, 表示它們都使用 docker 驅(qū)動程序。

buildx 支持以下幾種驅(qū)動程序:

驅(qū)動 說明
docker 使用捆綁到 Docker 守護(hù)進(jìn)程中的 BuildKit 庫, 就是安裝 Docker 后默認(rèn)的 BuildKit。
docker-container 使用 Docker 新創(chuàng)建一個專用的 BuildKit 容器。
kubernetes 在 Kubernetes 集群中創(chuàng)建一個 BuildKit Pod。
remote 直接連接到手動管理的 BuildKit 守護(hù)進(jìn)程。

默認(rèn)的 docker 驅(qū)動程序優(yōu)先考慮簡單性和易用性, 所以它對緩存和輸出格式等高級功能的支持有限, 并且不可配置。其他驅(qū)動程序則提供了更大的靈活性, 并且更擅長處理高級場景。

具體差異你可以到官方文檔中查看。

因為使用 docker 驅(qū)動程序的默認(rèn) builder 不支持使用單條命令(默認(rèn) builder 的 --platform 參數(shù)只接受單個值)構(gòu)建跨平臺鏡像, 所以我們需要使用 docker-container 驅(qū)動創(chuàng)建一個新的 builder。

命令語法如下:

$ docker buildx create --name=<builder-name> --driver=<driver> --driver-opt=<driver-options>

參數(shù)含義如下:

  • –name: 構(gòu)建器名稱, 必填。
  • –driver: 構(gòu)建器驅(qū)動程序, 默認(rèn)為 docker-container。
  • –driver-opt: 驅(qū)動程序選項, 如選項 --driver-opt=image=moby/buildkit:v0.11.3 可以安裝指定版本的 BuildKit, 默認(rèn)值是 moby/buildkit。

更多可選參數(shù)可以參考官方文檔。

我們可以使用如下命令創(chuàng)建一個新的 builder:

$ docker buildx create --name mybuilder
mybuilder

再次查看 builder 列表:

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

可以發(fā)現(xiàn)選中的構(gòu)建器已經(jīng)切換到了 mybuilder, 如果沒有選中, 你需要手動使用 docker buildx use mybuilder 命令切換構(gòu)建器。

1.6. 啟動 builder

我們新創(chuàng)建的 mybuilder 當(dāng)前狀態(tài)為 inactive, 需要啟動才能使用。

$ docker buildx inspect --bootstrap mybuilder
[+] Building 16.8s (1/1) FINISHED
 => [internal] booting buildkit                                                                                                                                  16.8s
 => => pulling image moby/buildkit:buildx-stable-1                                                                                                               16.1s
 => => creating container buildx_buildkit_mybuilder0                                                                                                              0.7s
Name:   mybuilder
Driver: docker-container

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

inspect 子命令用來檢查構(gòu)建器狀態(tài), 使用 --bootstrap 參數(shù)則可以啟動 mybuilder 構(gòu)建器。

再次查看 builder 列表, mybuilder 狀態(tài)已經(jīng)變成了 running。

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

其中 PLATFORMS 一列所展示的值 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6 就是當(dāng)前構(gòu)建器所支持的所有平臺了。

現(xiàn)在使用 docker ps 命令可以看到 mybuilder 構(gòu)建器所對應(yīng)的 BuildKit 容器已經(jīng)啟動。

$ docker ps
CONTAINER ID   IMAGE                           COMMAND                  CREATED         STATUS         PORTS                                NAMES
b8887f253d41   moby/buildkit:buildx-stable-1   "buildkitd"              4 minutes ago   Up 4 minutes                                        buildx_buildkit_mybuilder0

這個容器就是輔助我們構(gòu)建跨平臺鏡像用的, 不要手動刪除它。

1.7. 使用 builder 構(gòu)建跨平臺鏡像

現(xiàn)在一些準(zhǔn)備工作已經(jīng)就緒, 我們終于可以使用 builder 構(gòu)建跨平臺鏡像了。

這里以一個 Go 程序為例, 來演示如何構(gòu)建跨平臺鏡像。

hello.go 程序如下:

package main

import (
    "fmt"
    "runtime"
)

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

這個程序非常簡單, 執(zhí)行后打印 Hello, 操作系統(tǒng)/CPU 架構(gòu)。

Go 程序還需要一個 go.mod 文件:

module hello

go 1.20

編寫 Dockerfile 內(nèi)容如下:

FROM golang:1.20-alpine AS builder
WORKDIR /app
ADD . .
RUN go build -o hello .

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

這是一個普通的 Dockerfile 文件, 為了減小鏡像大小, 使用了多階段構(gòu)建。它跟構(gòu)建僅支持當(dāng)前平臺的鏡像所使用的 Dockerfile 沒什么兩樣。

$ ls
Dockerfile go.mod     hello.go

以上三個文件需要放在同一個目錄下, 然后就可以在這個目錄下使用 docker buildx 來構(gòu)建跨平臺鏡像了。

$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go .

docker buildx build 語法跟 docker build 一樣, --platform 參數(shù)表示構(gòu)建鏡像的目標(biāo)平臺, -t 表示鏡像的 Tag, . 表示上下文為當(dāng)前目錄。

唯一不同的是對 --platform 參數(shù)的支持, docker build 的 --platform 參數(shù)只支持傳遞一個平臺信息, 如 --platform linux/arm64, 也就是一次只能構(gòu)建單個平臺的鏡像。

而使用 docker buildx build 構(gòu)建鏡像則支持同時傳遞多個平臺信息, 中間使用英文逗號分隔, 這樣就實現(xiàn)了只用一條命令便可以構(gòu)建跨平臺鏡像的功能。

執(zhí)行以上命令后, 我們將會得到一條警告:

WARNING: No output specified with docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load

這條警告提示我們沒有為 docker-container 驅(qū)動程序指定輸出, 生成結(jié)果將只會保留在構(gòu)建緩存中, 使用 --push 可以將鏡像推送到 Docker Hub 遠(yuǎn)程倉庫, 使用 --load 可以將鏡像保存在本地。

這是因為我們新創(chuàng)建的 mybuilder 是啟動了一個容器來運(yùn)行 BuildKit, 它并不能直接將構(gòu)建好的跨平臺鏡像輸出到本機(jī)或推送到遠(yuǎn)程, 必須要用戶來手動指定輸出位置。

我們可以嘗試指定 --load 將鏡像保存的本地主機(jī)。

$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go . --load
[+] Building 0.0s (0/0)
ERROR: docker exporter does not currently support exporting manifest lists

結(jié)果會得到一條錯誤日志??磥硭⒉恢С种苯訉⒖缙脚_鏡像輸出到本機(jī), 這其實是因為傳遞了多個 --platform 的關(guān)系, 如果 --platform 只傳遞了一個平臺, 則可以使用 --load 將構(gòu)建好的鏡像輸出到本機(jī)。

那么我們就只能通過 --push 參數(shù)將跨平臺鏡像推送到遠(yuǎn)程倉庫了。不過在此之前需要確保使用 docker login 完成登錄。

$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go . --push

現(xiàn)在登錄 Docker Hub 就可以看見推送上來的跨平臺鏡像了。

我們也可以使用 imagetools 來檢查跨平臺鏡像的 manifest 信息。

$ docker buildx imagetools inspect jianghushinian/hello-go
Name:      docker.io/jianghushinian/hello-go:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest:    sha256:51199dadfc55b23d6ab5cfd2d67e38edd513a707273b1b8b554985ff562104db

Manifests:
  Name:      docker.io/jianghushinian/hello-go:latest@sha256:8032a6f23f3bd3050852e77b6e4a4d0a705dfd710fb63bc4c3dc9d5e01c8e9a6
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm64

  Name:      docker.io/jianghushinian/hello-go:latest@sha256:fd46fd7e93c7deef5ad8496c2cf08c266bac42ac77f1e444e83d4f79d58441ba
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/amd64

可以看到, 這個跨平臺鏡像包含了兩個目標(biāo)平臺的鏡像, 分別是 linux/arm64 和 linux/amd64。

我們分別在 Apple M2 芯片平臺和 Linux x86 平臺來啟動這個 Docker 鏡像看下輸出結(jié)果。

$ docker run --rm jianghushinian/hello-go
Hello, linux/arm64!
$ docker run --rm jianghushinian/hello-go
Hello, linux/amd64!

至此, 我們使用 builder 完成了跨平臺鏡像的構(gòu)建。

1.8. 使用交叉編譯

以上演示的構(gòu)建跨平臺鏡像過程就是利用 QEMU 的能力, 因為 Go 語言的交叉編譯非常簡單, 所以我們再來演示一下如何使用交叉編譯來構(gòu)建跨平臺鏡像。

我們只需要對 Dockerfile 文件進(jìn)行修改:

FROM --platform=$BUILDPLATFORM golang:1.20-alpine AS builder
ARG TARGETOS
ARG TARGETARCH
WORKDIR /app
ADD . .
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o hello .

FROM --platform=$TARGETPLATFORM alpine:latest
WORKDIR /app
COPY --from=builder /app/hello .
CMD ["./hello"]

其中 BUILDPLATFORM、TARGETOS、TARGETARCH、TARGETPLATFORM 四個變量是 BuildKit 提供的全局變量, 分別表示構(gòu)建鏡像所在平臺、操作系統(tǒng)、架構(gòu)、構(gòu)建鏡像的目標(biāo)平臺。

在構(gòu)建鏡像時, BuildKit 會將當(dāng)前所在平臺信息傳遞給 Dockerfile 中的 BUILDPLATFORM 參數(shù)(如 linux/arm64)。

通過 --platform 參數(shù)傳遞的 linux/arm64,linux/amd64 鏡像目標(biāo)平臺列表會依次傳遞給 TARGETPLATFORM 變量。

而 TARGETOS、TARGETARCH 兩個變量在使用時則需要先通過 ARG 進(jìn)行聲明, BuildKit 會自動為其賦值。

在 Go 程序進(jìn)行編譯時, 可以通過 GOOS 環(huán)境變量指定目標(biāo)操作系統(tǒng), 通過 GOARCH 環(huán)境變量指定目標(biāo)架構(gòu)。

所以這個 Dockerfile 所表示的含義是: 首先拉取當(dāng)前構(gòu)建鏡像所在平臺的 golang 鏡像, 然后使用交叉編譯構(gòu)建目標(biāo)平臺的 Go 程序, 最后將構(gòu)建好的 Go 程序復(fù)制到目標(biāo)平臺的 alpine 鏡像。

最終我們會通過交叉編譯得到一個跨平臺鏡像。

筆記: 通過 FROM --platform=$BUILDPLATFORM image 可以拉取指定平臺的鏡像, 由此我們可以知道, 其實 golang 和 alpine 鏡像都是支持跨平臺的。

構(gòu)建鏡像命令不變:

$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-cross-go . --push

啟動鏡像后輸出結(jié)果不變:

$ docker run --rm jianghushinian/hello-cross-go
Hello, linux/arm64!
$ docker run --rm jianghushinian/hello-cross-go
Hello, linux/amd64!

至此, 我們利用 Go 語言的交叉編譯完成了跨平臺鏡像的構(gòu)建。

1.9. 平臺相關(guān)的全局變量

關(guān)于上面提到的幾個全局變量, BuildKit 后端預(yù)定義了一組 ARG 全局變量(共 8 個)可供使用, 其定義和說明如下:

變量 說明
TARGETPLATFORM 構(gòu)建鏡像的目標(biāo)平臺, 如: linux/amd64, linux/arm/v7, windows/amd64。
TARGETOS TARGETPLATFORM 的操作系統(tǒng), 如: linux、windows。
TARGETARCH TARGETPLATFORM 的架構(gòu)類型, 如: amd64、arm。
TARGETVARIANT TARGETPLATFORM 的變體, 如: v7。
BUILDPLATFORM 執(zhí)行構(gòu)建所在的節(jié)點平臺。
BUILDOS BUILDPLATFORM 的操作系統(tǒng)。
BUILDARCH BUILDPLATFORM 的架構(gòu)類型。
BUILDVARIANT BUILDPLATFORM 的變體。

使用示例如下:

# 這里可以直接使用 TARGETPLATFORM 變量
FROM --platform=$TARGETPLATFORM alpine

# 稍后的 RUN 命令想要使用變量必須提前用 ARG 進(jìn)行聲明
ARG TARGETPLATFORM

RUN echo "I'm building for $TARGETPLATFORM"

1.10. 刪除 builder

我們已經(jīng)實現(xiàn)了使用 builder 構(gòu)建跨平臺鏡像。如果現(xiàn)在你想要恢復(fù)環(huán)境, 刪除新建的 builder。則可以使用 docker buildx rm mybuilder 命令來完成。

$ docker buildx rm mybuilder
mybuilder removed

跟隨 mybuilder 啟動的 buildx_buildkit_mybuilder0 容器也會隨之被刪除。

現(xiàn)在再使用 docker buildx ls 命令查看構(gòu)建器列表, 已經(jīng)恢復(fù)成原來的樣子了。

$ docker buildx ls
NAME/NODE       DRIVER/ENDPOINT STATUS  BUILDKIT PLATFORMS
default *       docker
  default       default         running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
desktop-linux   docker
  desktop-linux desktop-linux   running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

1.11. 功能清單

除了前文介紹的幾個 buildx 常用命令, 更多功能可以通過 --help 參數(shù)進(jìn)行查看。

$ docker buildx --help

Usage:  docker buildx [OPTIONS] COMMAND

Extended build capabilities with BuildKit

Options:
      --builder string   Override the configured builder instance

Management Commands:
  imagetools  Commands to work on images in registry

Commands:
  bake        Build from a file
  build       Start a build
  create      Create a new builder instance
  du          Disk usage
  inspect     Inspect current builder instance
  ls          List builder instances
  prune       Remove build cache
  rm          Remove a builder instance
  stop        Stop builder instance
  use         Set the current builder instance
  version     Show buildx version information

Run 'docker buildx COMMAND --help' for more information on a command.

如 stop、rm 可以管理 builder 的生命周期。每條子命令又可以使用 docker buildx COMMAND --help 方式查看使用幫助, 感興趣的同學(xué)可以自行學(xué)習(xí)。

1.12. 總結(jié)

本文講解了如何使用 buildx 構(gòu)建跨平臺鏡像, 這也是在 Docker 生態(tài)中目前最優(yōu)的構(gòu)建方式。

首先介紹了 buildx 是什么, 以及如何安裝。接下來就進(jìn)入了構(gòu)建跨平臺鏡像的講解, 我們分析了三種跨平臺鏡像構(gòu)建策略, 并且分別對 QEMU 和 交叉編譯兩種策略進(jìn)行了演示。QEMU 策略無需對 Dockerfile 做任何更改, 而使用交叉編譯方式則需要根據(jù)程序的支持來編寫 Dockerfile 構(gòu)建跨平臺應(yīng)用。

最后我們還講解了如何管理 buildx 的生命周期, 以及羅列了 buildx 的功能清單幫助你進(jìn)一步深入學(xué)習(xí)。

2. 使用 docker manifest 構(gòu)建跨平臺鏡像

在當(dāng)今的軟件開發(fā)領(lǐng)域中, 構(gòu)建跨平臺應(yīng)用程序已經(jīng)成為了一個普遍存在的需求。不同的操作系統(tǒng)、硬件架構(gòu)需要不同的鏡像環(huán)境來支持它們。Docker 作為一個廣泛應(yīng)用的容器化技術(shù), 必然需要能夠支持構(gòu)建跨平臺鏡像, 本文將介紹如何使用 docker manifest 來實現(xiàn)構(gòu)建跨平臺鏡像。

2.1. 簡介

docker manifest 是 Docker 的一個命令, 它提供了一種方便的方式來管理不同操作系統(tǒng)和硬件架構(gòu)的 Docker 鏡像。通過 docker manifest, 用戶可以創(chuàng)建一個虛擬的 Docker 鏡像, 其中包含了多個實際的 Docker 鏡像, 每個實際的 Docker 鏡像對應(yīng)一個不同的操作系統(tǒng)和硬件架構(gòu)。

docker manifest 命令本身并不執(zhí)行任何操作。為了操作一個 manifest 或 manifest list, 必須使用其中一個子命令。

manifest 可以理解為是一個 JSON 文件, 單個 manifest 包含有關(guān)鏡像的信息, 例如層 (layers)、大小 (size) 和摘要 (digest) 等。

manifest list 是通過指定一個或多個(理想情況下是多個)鏡像名稱創(chuàng)建的鏡像列表(即上面所說的虛擬 Docker 鏡像)??梢韵衿胀ㄧR像一樣使用 docker pull 和 docker run 等命令來操作它。manifest list 通常被稱為「多架構(gòu)鏡像」。

注意: docker manifest 命令是實驗性的, 還未轉(zhuǎn)正。旨在用于測試和反饋, 因此其功能和用法可能會在不同版本之間發(fā)生變化。

2.2. 準(zhǔn)備工作

工欲善其事, 必先利其器, 如果想使用 docker manifest 構(gòu)建多架構(gòu)鏡像, 需要具備以下條件。

  • 機(jī)器上安裝了 Docker。
  • 需要注冊一個 Docker Hub 賬號。
  • 最少有兩個不同平臺的主機(jī), 用來驗證 docker manifest 鎖構(gòu)建出來的多架構(gòu)鏡像正確性(可選)。
  • 聯(lián)網(wǎng), docker manifest 命令是需要聯(lián)網(wǎng)使用的。

2.3. 為不同平臺構(gòu)建鏡像

本文中演示程序所使用的環(huán)境是 Apple M2 芯片平臺。本地的 Docker 版本如下:

$ docker version
Client:
 Cloud integration: v1.0.29
 Version:           20.10.21
 API version:       1.41
 Go version:        go1.18.7
 Git commit:        baeda1f
 Built:             Tue Oct 25 18:01:18 2022
 OS/Arch:           darwin/arm64
 Context:           default
 Experimental:      true

Server: Docker Desktop 4.15.0 (93002)
 Engine:
  Version:          20.10.21
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.18.7
  Git commit:       3056208
  Built:            Tue Oct 25 17:59:41 2022
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.6.10
  GitCommit:        770bd0108c32f3fb5c73ae1264f7e503fe7b2661
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

2.4. 準(zhǔn)備 Dockerfile

首先準(zhǔn)備如下 Dockerfile 文件, 用來構(gòu)建鏡像。

FROM alpine

RUN uname -a > /os.txt

CMD cat /os.txt

這個鏡像非常簡單, 構(gòu)建時將 uname -a 命令輸出信息(即當(dāng)前操作系統(tǒng)的相關(guān)信息)寫入 /os.txt, 運(yùn)行時將 /os.txt 內(nèi)容輸出。

2.5. 構(gòu)建 arm64 平臺鏡像

因為本機(jī)為 Apple M2 芯片, 所以使用 docker build 命令構(gòu)建鏡像默認(rèn)為 arm64 平臺鏡像。構(gòu)建命令如下:

$ docker build -t jianghushinian/echo-platform-arm64 .
[+] Building 15.6s (6/6) FINISHED
 => [internal] load build definition from Dockerfile                                             0.0s
 => => transferring dockerfile: 94B                                                              0.0s
 => [internal] load .dockerignore                                                                0.0s
 => => transferring context: 2B                                                                  0.0s
 => [internal] load metadata for docker.io/library/alpine:latest                                15.5s
 => [1/2] FROM docker.io/library/alpine@sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc01  0.0s
 => CACHED [2/2] RUN uname -a > /os.txt                                                          0.0s
 => exporting to image                                                                           0.0s
 => => exporting layers                                                                          0.0s
 => => writing image sha256:f017783a39920aa4646f87d7e5a2d67ab51aab479147d60e5372f8749c3742bb     0.0s
 => => naming to docker.io/jianghushinian/echo-platform-arm64                                    0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

注意: jianghushinian 是我的 Docker Hub 用戶名, 你在構(gòu)建鏡像時應(yīng)該使用自己的 Docker Hub 用戶名。

如果得到如上類似輸出, 表明構(gòu)建成功。

使用 docker run 運(yùn)行容器進(jìn)行測試:

$ docker run --rm jianghushinian/echo-platform-arm64
Linux buildkitsandbox 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022 aarch64 Linux

輸出內(nèi)容中的 aarch64 就表示 ARMv8 架構(gòu)。

現(xiàn)在我們需要將鏡像推送到 Docker Hub, 確保在命令行中已經(jīng)使用 docker login 登錄過 Docker Hub 的情況下, 使用 docker push 命令推送鏡像:

$ docker push jianghushinian/echo-platform-arm64
Using default tag: latest
The push refers to repository [docker.io/jianghushinian/echo-platform-arm64]
dd0468cb6cb1: Pushed
07d3c46c9599: Mounted from jianghushinian/demo-arm64
latest: digest: sha256:8eb172234961bf54a01e83d510697f09646c43c297a24f839be846414dfaf583 size: 735

瀏覽器中登錄 Docker Hub 查看推送成功的鏡像:

2.6. 構(gòu)建 amd64 平臺鏡像

無需切換設(shè)備, 在 Apple M2 芯片的機(jī)器上我們可以直接構(gòu)建 amd64 也就是 Linux 平臺鏡像, docker build 命令提供了 --platform 參數(shù)可以構(gòu)建跨平臺鏡像。

$ docker build --platform=linux/amd64 -t jianghushinian/echo-platform-amd64 .
[+] Building 15.7s (6/6) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                                      0.0s
 => => transferring dockerfile: 36B                                                                                                                                       0.0s
 => [internal] load .dockerignore                                                                                                                                         0.0s
 => => transferring context: 2B                                                                                                                                           0.0s
 => [internal] load metadata for docker.io/library/alpine:latest                                                                                                         15.3s
 => CACHED [1/2] FROM docker.io/library/alpine@sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300                                                    0.0s
 => [2/2] RUN uname -a > /os.txt                                                                                                                                          0.2s
 => exporting to image                                                                                                                                                    0.0s
 => => exporting layers                                                                                                                                                   0.0s
 => => writing image sha256:5c48af5176402727627cc18136d78f87f0793ccf61e3e3fb4df98391a69e9f70                                                                              0.0s
 => => naming to docker.io/jianghushinian/echo-platform-amd64                                                                                                             0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

鏡像構(gòu)建成功后, 同樣使用 docker push 命令推送鏡像到 Docker Hub:

$ docker push jianghushinian/echo-platform-amd64
Using default tag: latest
The push refers to repository [docker.io/jianghushinian/echo-platform-amd64]
9499dee27c9f: Pushed
8d3ac3489996: Mounted from jianghushinian/demo-amd64
latest: digest: sha256:13cbf21fc8078fb54444992faae9aafca0706a842dfb0ab4f3447a6f14fb1359 size: 735

瀏覽器中登錄 Docker Hub 查看推送成功的鏡像:

你也許會好奇, 在 Apple M2 芯片的主機(jī)設(shè)備上運(yùn)行 amd64 平臺鏡像會怎樣。目前咱們構(gòu)建的這個簡單鏡像其實是能夠運(yùn)行的, 只不過會得到一條警告信息:

$ docker run --rm jianghushinian/echo-platform-amd64
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Linux buildkitsandbox 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022 x86_64 Linux

輸出內(nèi)容中的 x86_64 就表示 AMD64 架構(gòu)。

注意: 雖然這個簡單的鏡像能夠運(yùn)行成功, 但如果容器內(nèi)部程序不支持跨平臺, amd64 平臺鏡像無法在 arm64 平臺運(yùn)行成功。

同樣的, 如果我們登錄到一臺 amd64 架構(gòu)的設(shè)備上運(yùn)行 arm64 平臺鏡像, 也會得到一條警告信息:

# docker run --rm jianghushinian/echo-platform-arm64
WARNING: The requested image's platform (linux/arm64/v8) does not match the detected host platform (linux/amd64) and no specific platform was requested
Linux buildkitsandbox 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022 aarch64 Linux

在 amd64 架構(gòu)的設(shè)備上運(yùn)行 amd64 平臺鏡像則不會遇到警告問題:

# docker run --rm jianghushinian/echo-platform-amd64
Linux buildkitsandbox 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022 x86_64 Linux

2.7. 使用 manifest 合并多平臺鏡像

我們可以使用 docker manifest 的子命令 create 創(chuàng)建一個 manifest list, 即將多個平臺的鏡像合并為一個鏡像。

create 命令用法很簡單, 后面跟的第一個參數(shù) jianghushinian/echo-platform 即為合并后的鏡像, 從第二個參數(shù)開始可以指定一個或多個不同平臺的鏡像。

$ docker manifest create jianghushinian/echo-platform jianghushinian/echo-platform-arm64 jianghushinian/echo-platform-amd64
Created manifest list docker.io/jianghushinian/echo-platform:latest

如上輸出, 表明多架構(gòu)鏡像構(gòu)建成功。

注意: 在使用 docker manifest create 命令時, 確保待合并鏡像都已經(jīng)被推送到 Docker Hub 鏡像倉庫, 不然報錯 no such manifest。這也是為什么前文在構(gòu)建鏡像時, 都會將鏡像推送到 Docker Hub。

此時在 Apple M2 芯片設(shè)備上使用 docker run 啟動構(gòu)建好的跨平臺鏡像 jianghushinian/echo-platform:

$ docker run --rm jianghushinian/echo-platform
Linux buildkitsandbox 5.4.0-80-generic #90-Ubuntu SMP Fri Jul 9 22:49:44 UTC 2021 aarch64 Linux

沒有任何問題, 就像在啟動 jianghushinian/echo-platform-arm64 鏡像一樣。

現(xiàn)在我們可以將這個跨平臺鏡像推送到 Docker Hub, 不過, 這回我們需要使用的命令不再是 docker push 而是 manifest 的子命令 docker manifest push:

$ docker manifest push jianghushinian/echo-platform
Pushed ref docker.io/jianghushinian/echo-platform@sha256:13cbf21fc8078fb54444992faae9aafca0706a842dfb0ab4f3447a6f14fb1359 with digest: sha256:13cbf21fc8078fb54444992faae9aafca0706a842dfb0ab4f3447a6f14fb1359
Pushed ref docker.io/jianghushinian/echo-platform@sha256:8eb172234961bf54a01e83d510697f09646c43c297a24f839be846414dfaf583 with digest: sha256:8eb172234961bf54a01e83d510697f09646c43c297a24f839be846414dfaf583
sha256:87b51c1835f13bb722bbb4279fcf50a6da0ecb852433a8f1c04e2f5fe93ac055

瀏覽器中登錄 Docker Hub 查看推送成功的鏡像:

進(jìn)入鏡像信息詳情頁面的 Tags 標(biāo)簽, 能夠看到鏡像支持 amd64、arm64/v8 這兩個平臺。

現(xiàn)在, 我們可以在 amd64 架構(gòu)的設(shè)備上同樣使用 docker run 命令啟動構(gòu)建好的跨平臺鏡像 jianghushinian/echo-platform:

# docker run --rm jianghushinian/echo-platform
Linux buildkitsandbox 5.4.0-80-generic #90-Ubuntu SMP Fri Jul 9 22:49:44 UTC 2021 x86_64 Linux

輸出結(jié)果沒有任何問題??梢园l(fā)現(xiàn), 無論是 arm64 設(shè)備還是 amd64 設(shè)備, 雖然同樣使用 docker run --rm jianghushinian/echo-platform 命令啟動鏡像, 但它們的輸出結(jié)果都表明啟動的是當(dāng)前平臺的鏡像, 沒有再次出現(xiàn)警告。

2.8. manifest 功能清單

docker manifest 不止有 create 一個子命令, 可以通過 --help/-h 參數(shù)查看使用幫助:

$ docker manifest --help

Usage:  docker manifest COMMAND

The **docker manifest** command has subcommands for managing image manifests and
manifest lists. A manifest list allows you to use one name to refer to the same image
built for multiple architectures.

To see help for a subcommand, use:

    docker manifest CMD --help

For full details on using docker manifest lists, see the registry v2 specification.

EXPERIMENTAL:
  docker manifest is an experimental feature.
  Experimental features provide early access to product functionality. These
  features may change between releases without warning, or can be removed from a
  future release. Learn more about experimental features in our documentation:
  https://docs.docker.com/go/experimental/

Commands:
  annotate    Add additional information to a local image manifest
  create      Create a local manifest list for annotating and pushing to a registry
  inspect     Display an image manifest, or manifest list
  push        Push a manifest list to a repository
  rm          Delete one or more manifest lists from local storage

Run 'docker manifest COMMAND --help' for more information on a command.

可以發(fā)現(xiàn), docker manifest 共提供了 annotate、create、inspect、push、rm 這 5 個子命。

接下來我們分別看下這幾個子命令的功能。

2.9. create

先從最熟悉的 create 子命令看起, 來看下它都支持哪些功能。

$ docker manifest create -h
Flag shorthand -h has been deprecated, please use --help

Usage:  docker manifest create MANIFEST_LIST MANIFEST [MANIFEST...]

Create a local manifest list for annotating and pushing to a registry

EXPERIMENTAL:
  docker manifest create is an experimental feature.
  Experimental features provide early access to product functionality. These
  features may change between releases without warning, or can be removed from a
  future release. Learn more about experimental features in our documentation:
  https://docs.docker.com/go/experimental/

Options:
  -a, --amend      Amend an existing manifest list
      --insecure   Allow communication with an insecure registry

筆記: 可以看到輸出結(jié)果第一行的提示, 短標(biāo)志 -h 已經(jīng)被棄用, 推薦使用 --help 查看子命令幫助信息。

可以發(fā)現(xiàn), create 子命令支持兩個可選參數(shù) -a/–amend 用來修訂已存在的多架構(gòu)鏡像。

指定 --insecure 參數(shù)則允許使用不安全的(非 https) 鏡像倉庫。

2.10. push

push 子命令我們也見過了, 使用 push 可以將多架構(gòu)鏡像推送到鏡像倉庫。

來看下 push 還支持設(shè)置哪些可選參數(shù)。

$ docker manifest push -h
Flag shorthand -h has been deprecated, please use --help

Usage:  docker manifest push [OPTIONS] MANIFEST_LIST

Push a manifest list to a repository

EXPERIMENTAL:
  docker manifest push is an experimental feature.
  Experimental features provide early access to product functionality. These
  features may change between releases without warning, or can be removed from a
  future release. Learn more about experimental features in our documentation:
  https://docs.docker.com/go/experimental/

Options:
      --insecure   Allow push to an insecure registry
  -p, --purge      Remove the local manifest list after push

同樣的, push 也有一個 --insecure 參數(shù)允許使用不安全的(非 https) 鏡像倉庫。

-p/--purge 選項的作用是推送本地鏡像到遠(yuǎn)程倉庫后, 刪除本地 manifest list。

2.11. inspect

inspect 用來查看 manifest/manifest list 所包含的鏡像信息。

其使用幫助如下:

$ docker manifest inspect -h
Flag shorthand -h has been deprecated, please use --help

Usage:  docker manifest inspect [OPTIONS] [MANIFEST_LIST] MANIFEST

Display an image manifest, or manifest list

EXPERIMENTAL:
  docker manifest inspect is an experimental feature.
  Experimental features provide early access to product functionality. These
  features may change between releases without warning, or can be removed from a
  future release. Learn more about experimental features in our documentation:
  https://docs.docker.com/go/experimental/

Options:
      --insecure   Allow communication with an insecure registry
  -v, --verbose    Output additional info including layers and platform

--insecure 參數(shù)允許使用不安全的(非 https) 鏡像倉庫。這已經(jīng)是我們第三次看見這個參數(shù)了, 這也驗證了 docker manifest 命令需要聯(lián)網(wǎng)才能使用的說法, 因為這些子命令基本都涉及到和遠(yuǎn)程鏡像倉庫的交互。

指定 -v/--verbose 參數(shù)可以輸出更多信息, 包括鏡像的 layers 和 platform 信息。

使用示例如下:

$ docker manifest inspect jianghushinian/echo-platform
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 735,
         "digest": "sha256:13cbf21fc8078fb54444992faae9aafca0706a842dfb0ab4f3447a6f14fb1359",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 735,
         "digest": "sha256:8eb172234961bf54a01e83d510697f09646c43c297a24f839be846414dfaf583",
         "platform": {
            "architecture": "arm64",
            "os": "linux",
            "variant": "v8"
         }
      }
   ]
}

從輸出信息中可以發(fā)現(xiàn), 我們構(gòu)建的多架構(gòu)鏡像 jianghushinian/echo-platform 包含兩個 manifest, 可以支持 amd64/arm64 架構(gòu), 并且都為 linux 系統(tǒng)下的鏡像。

指定 -v 參數(shù)輸出更詳細(xì)信息:

$ docker manifest inspect -v jianghushinian/echo-platform
[
	{
		"Ref": "docker.io/jianghushinian/echo-platform:latest@sha256:13cbf21fc8078fb54444992faae9aafca0706a842dfb0ab4f3447a6f14fb1359",
		"Descriptor": {
			"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
			"digest": "sha256:13cbf21fc8078fb54444992faae9aafca0706a842dfb0ab4f3447a6f14fb1359",
			"size": 735,
			"platform": {
				"architecture": "amd64",
				"os": "linux"
			}
		},
		"SchemaV2Manifest": {
			"schemaVersion": 2,
			"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
			"config": {
				"mediaType": "application/vnd.docker.container.image.v1+json",
				"size": 1012,
				"digest": "sha256:5c48af5176402727627cc18136d78f87f0793ccf61e3e3fb4df98391a69e9f70"
			},
			"layers": [
				{
					"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
					"size": 2818413,
					"digest": "sha256:59bf1c3509f33515622619af21ed55bbe26d24913cedbca106468a5fb37a50c3"
				},
				{
					"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
					"size": 211,
					"digest": "sha256:1e5897976ad1d3969268a18f4f0356a05875baf0225e39768a9066f43e950ebd"
				}
			]
		}
	},
	{
		"Ref": "docker.io/jianghushinian/echo-platform:latest@sha256:8eb172234961bf54a01e83d510697f09646c43c297a24f839be846414dfaf583",
		"Descriptor": {
			"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
			"digest": "sha256:8eb172234961bf54a01e83d510697f09646c43c297a24f839be846414dfaf583",
			"size": 735,
			"platform": {
				"architecture": "arm64",
				"os": "linux",
				"variant": "v8"
			}
		},
		"SchemaV2Manifest": {
			"schemaVersion": 2,
			"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
			"config": {
				"mediaType": "application/vnd.docker.container.image.v1+json",
				"size": 1027,
				"digest": "sha256:f017783a39920aa4646f87d7e5a2d67ab51aab479147d60e5372f8749c3742bb"
			},
			"layers": [
				{
					"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
					"size": 2715434,
					"digest": "sha256:9b3977197b4f2147bdd31e1271f811319dcd5c2fc595f14e81f5351ab6275b99"
				},
				{
					"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
					"size": 212,
					"digest": "sha256:edf2b8e1db64e4f46a2190a3dfcb74ae131ae13ad43fcfedde4c3f304c451f7d"
				}
			]
		}
	}
]

2.12. annotate

annotate 子命令可以給一個本地鏡像 manifest 添加附加的信息。這有點像 K8s Annotations 的意思。

其使用幫助如下:

$ docker manifest annotate -h
Flag shorthand -h has been deprecated, please use --help

Usage:  docker manifest annotate [OPTIONS] MANIFEST_LIST MANIFEST

Add additional information to a local image manifest

EXPERIMENTAL:
  docker manifest annotate is an experimental feature.
  Experimental features provide early access to product functionality. These
  features may change between releases without warning, or can be removed from a
  future release. Learn more about experimental features in our documentation:
  https://docs.docker.com/go/experimental/

Options:
      --arch string           Set architecture
      --os string             Set operating system
      --os-features strings   Set operating system feature
      --os-version string     Set operating system version
      --variant string        Set architecture variant

可選參數(shù)列表如下:

選項 描述
–arch 設(shè)置 CPU 架構(gòu)信息。
–os 設(shè)置操作系統(tǒng)信息。
–os-features 設(shè)置操作系統(tǒng)功能信息。
–os-version 設(shè)置操作系統(tǒng)版本信息。
–variant 設(shè)置 CPU 架構(gòu)的 variant 信息(翻譯過來是"變種"的意思), 如 ARM 架構(gòu)的 v7、v8 等。

例如設(shè)置操作系統(tǒng)版本信息, 可以使用如下命令:

$ docker manifest annotate --os-version macOS jianghushinian/echo-platform jianghushinian/echo-platform-arm64

現(xiàn)在使用 inspect 查看鏡像信息已經(jīng)發(fā)生變化:

{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 735,
         "digest": "sha256:13cbf21fc8078fb54444992faae9aafca0706a842dfb0ab4f3447a6f14fb1359",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 735,
         "digest": "sha256:8eb172234961bf54a01e83d510697f09646c43c297a24f839be846414dfaf583",
         "platform": {
            "architecture": "arm64",
            "os": "linux",
            "os.version": "macOS",
            "variant": "v8"
         }
      }
   ]
}

2.13. rm

最后要介紹的子命令是 rm, 使用 rm 可以刪除本地一個或多個多架構(gòu)鏡像 (manifest lists)。

$ docker manifest rm -h
Flag shorthand -h has been deprecated, please use --help

Usage:  docker manifest rm MANIFEST_LIST [MANIFEST_LIST...]

Delete one or more manifest lists from local storage

EXPERIMENTAL:
  docker manifest rm is an experimental feature.
  Experimental features provide early access to product functionality. These
  features may change between releases without warning, or can be removed from a
  future release. Learn more about experimental features in our documentation:
  https://docs.docker.com/go/experimental/

使用示例如下:

$ docker manifest rm jianghushinian/echo-platform

現(xiàn)在使用 inspect 查看鏡像信息已經(jīng)不在有 os.version 信息了, 因為本地鏡像 manifest lists 信息已經(jīng)被刪除, 重新從遠(yuǎn)程鏡像倉庫拉下來的多架構(gòu)鏡像信息并不包含 os.version。

$ docker manifest inspect jianghushinian/echo-platform
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 735,
         "digest": "sha256:13cbf21fc8078fb54444992faae9aafca0706a842dfb0ab4f3447a6f14fb1359",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 735,
         "digest": "sha256:8eb172234961bf54a01e83d510697f09646c43c297a24f839be846414dfaf583",
         "platform": {
            "architecture": "arm64",
            "os": "linux",
            "variant": "v8"
         }
      }
   ]
}

2.14. 總結(jié)

本文主要介紹了如何使用 docker manifest 來實現(xiàn)構(gòu)建跨平臺鏡像。

首先對 docker manifest 進(jìn)行了簡單介紹, 它是 Docker 的一個子命令, 本身并不執(zhí)行任何操作, 為了操作一個 manifest 或 manifest list, 必須使用它包含的子命令。

接著我們又在 Apple M2 芯片設(shè)備上構(gòu)建了不同平臺的鏡像, 然后使用 manifest list 的能力將其合并成跨平臺鏡像。

最后對 docker manifest 支持的所有子命令都進(jìn)行了講解。

2.15. 參考

docker manifest 官方文檔: https://docs.docker.com/engine/reference/commandline/manifest/文章來源地址http://www.zghlxwxcb.cn/news/detail-768179.html

到了這里,關(guān)于使用 docker buildx 構(gòu)建跨平臺鏡像 (QEMU/buildx/build)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • NativePHP:使用PHP構(gòu)建跨平臺桌面應(yīng)用的新框架

    NativePHP是一個用于使用PHP構(gòu)建桌面應(yīng)用的框架。它允許PHP開發(fā)人員使用熟悉的工具和技術(shù)創(chuàng)建跨平臺的原生應(yīng)用。NativePHP具有一系列易于使用的類,一套用于構(gòu)建和打包應(yīng)用程序的工具以及一個靜態(tài)跨平臺PHP運(yùn)行時。 官網(wǎng)地址:https://nativephp.com PHP究竟是什么?嚴(yán)格地說,N

    2024年02月14日
    瀏覽(30)
  • Gitlab 使用 docker buildx 多重構(gòu)建鏡像上傳私有 Harbor與 Dockerhub

    Gitlab 使用 docker buildx 多重構(gòu)建鏡像上傳私有 Harbor與 Dockerhub

    三臺虛擬機(jī) 192.168.10.2 harbor 倉庫 192.168.10.3 gitlab-ce 192.168.10.4 gitlab-runner 192.168.10.5 開發(fā)平臺 系統(tǒng): CentOS Linux release 8.5.2111 CPU: 4c 內(nèi)存:8G 磁盤:40G 2.1 安裝 docker buidx buidx在 gitlab runner 節(jié)點安裝 默認(rèn)的 docker build 命令無法完成跨平臺構(gòu)建任務(wù),我們需要為 docker 命令行安裝 bu

    2024年02月17日
    瀏覽(34)
  • 【GTest】使用CMakeLitsts.txt構(gòu)建Windows和Linux的跨平臺GoogleTest項目(非常詳細(xì)+親測有效)

    【GTest】使用CMakeLitsts.txt構(gòu)建Windows和Linux的跨平臺GoogleTest項目(非常詳細(xì)+親測有效)

    ??博__主??:米碼收割機(jī) ??技__能??:C++/Python語言 ??公眾號??:測試開發(fā)自動化 ??專__注??:專注主流機(jī)器人、人工智能等相關(guān)領(lǐng)域的開發(fā)、測試技術(shù) Linux構(gòu)建參考我的文章:【點擊這里】 windows構(gòu)建靜態(tài)庫參考我的文章:【點擊這里】 (1)創(chuàng)建GtestAPI的文件夾,作為

    2024年02月07日
    瀏覽(35)
  • Flutter 實戰(zhàn):構(gòu)建跨平臺應(yīng)用

    Flutter 實戰(zhàn):構(gòu)建跨平臺應(yīng)用

    Flutter是由Google開發(fā)的一款開源移動應(yīng)用開發(fā)框架,它可以幫助開發(fā)者在iOS和Android平臺上快速、高效地開發(fā)應(yīng)用。Flutter使用Dart語言作為開發(fā)語言,具有跨平臺兼容性高、開發(fā)效率快、性能優(yōu)異等特點。本文將通過實戰(zhàn)案例,介紹如何使用Flutter構(gòu)建跨平臺應(yīng)用。 在開始Flutte

    2024年02月05日
    瀏覽(1262)
  • Flutter:構(gòu)建跨平臺應(yīng)用的未來選擇

    隨著移動設(shè)備的普及和技術(shù)的不斷發(fā)展,跨平臺移動應(yīng)用開發(fā)成為了一個熱門的需求。Flutter作為一款由Google開發(fā)的開源移動應(yīng)用開發(fā)框架,受到了越來越多的關(guān)注。本文將帶你了解Flutter的優(yōu)勢、應(yīng)用場景以及如何使用Flutter進(jìn)行開發(fā)。 一、Flutter的優(yōu)勢 1.跨平臺:Flutter使用

    2024年02月09日
    瀏覽(97)
  • x86 平臺利用 qemu-user-static 實現(xiàn) arm64 平臺 docker 鏡像的運(yùn)行和構(gòu)建

    x86 平臺利用 qemu-user-static 實現(xiàn) arm64 平臺 docker 鏡像的運(yùn)行和構(gòu)建

    因為國產(chǎn)化的普及,尤其一些證券和銀行行業(yè),已經(jīng)開始走信創(chuàng)的路線,后期也許會接觸到國產(chǎn) CPU ( arm 平臺,比如華為的鯤鵬處理器) 自己買 arm 平臺的 CPU ,這個成本著實吃不消,于是嘗試 x86 平臺運(yùn)行 arm 平臺的容器來降本增效 docker 運(yùn)行其他平臺容器,需要使用 --pla

    2024年02月02日
    瀏覽(44)
  • Kotlin MultiPlatform:構(gòu)建跨平臺應(yīng)用的未來

    Kotlin MultiPlatform:構(gòu)建跨平臺應(yīng)用的未來

    1.1 Kotlin MultiPlatform簡介 Kotlin MultiPlatform(簡稱KMP)是一種由JetBrains開發(fā)的跨平臺開發(fā)解決方案,它建立在Kotlin語言之上。KMP允許開發(fā)者使用一套Kotlin代碼來構(gòu)建適用于多個平臺的應(yīng)用程序,包括移動應(yīng)用、后端服務(wù)和嵌入式系統(tǒng)等。KMP提供了共享代碼的功能,同時也允許開發(fā)

    2024年04月17日
    瀏覽(86)
  • 構(gòu)建跨設(shè)備3D應(yīng)用:HOOPS的跨平臺開發(fā)能力

    構(gòu)建跨設(shè)備3D應(yīng)用:HOOPS的跨平臺開發(fā)能力

    在當(dāng)今數(shù)字化和可視化需求不斷提升的時代,三維技術(shù)的應(yīng)用越來越廣泛,尤其在制造、建筑、工程及媒體行業(yè)。HOOPS,由Tech Soft 3D開發(fā),是一套全面的軟件開發(fā)工具包,用于構(gòu)建高性能的三維應(yīng)用程序。該工具包涵蓋了從三維渲染到復(fù)雜數(shù)據(jù)交換的多個方面,支持廣泛的文

    2024年04月25日
    瀏覽(97)
  • 探索 Electron Egg:構(gòu)建跨平臺桌面應(yīng)用的理想選擇

    隨著Web技術(shù)的不斷發(fā)展,構(gòu)建跨平臺桌面應(yīng)用的需求也在逐漸增加。Electron Egg作為一個結(jié)合了Electron和Vue.js的框架,為開發(fā)者提供了一個簡單而強(qiáng)大的工具,使他們能夠快速構(gòu)建出優(yōu)秀的桌面應(yīng)用。本文將介紹Electron Egg的核心特性、優(yōu)勢以及如何開始使用這個框架。 什么是

    2024年02月20日
    瀏覽(27)
  • Docker多平臺、跨平臺編譯打包

    大多數(shù)帶有Docker官方標(biāo)識的鏡像都提供了多架構(gòu)支持。如:busybox鏡像支持 amd64 ,? arm32v5 ,? arm32v6 ,? arm32v7 ,? arm64v8 ,? i386 ,? ppc64le , and? s390x。 當(dāng)你在amd64設(shè)備上運(yùn)行容器時,會拉取amd64鏡像。 當(dāng)你需要構(gòu)建多平臺鏡像時,可以用 --platform 參數(shù)指定目標(biāo)平臺,但是通常情況下

    2024年02月06日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包