Docker構建多平臺映象

MartinDai發表於2024-06-10

多平臺映象使用場景

我們知道Docker映象是支援多平臺(不同的作業系統/架構)的,比如linux/amd64,linux/arm64,linux/riscv64等,當我們需要在不同平臺使用容器執行我們的映象的時候,通常可能會考慮分別編譯各個平臺的映象檔案,然後打上不同的tag用來區分平臺,使用的時候也同樣需要根據實際執行的平臺在配置檔案中選擇不同的tag,這樣就導致配置檔案無法良好的共用,使用起來相當的不方便。

多平臺映象就是解決此問題的一個方案,那麼什麼是多平臺映象呢?我們以MySQL的官方映象為例(Docker Hub上的大多數Docker官方映象都提供了多平臺映象)

1.png

可以看到,該映象支援在linux/amd64和linux/arm64平臺下執行,透過執行相同的命令docker pull mysql:8.0獲取映象,docker會自動根據manifest的描述找到並下載適合當前系統架構的映象檔案。

如此,便可以在多個平臺之間共用同一份配置檔案,而無需多餘的處理,是不是方便很多呢?


如何構建多平臺映象

接下來介紹兩種構建多平臺映象的方法

方法一(推薦)

此方法需要開啟docker的containerd-snapshotter特性

開啟containerd-snapshotter

修改/etc/docker/daemon.json檔案,新增

"features": {
  "containerd-snapshotter": true
}

2.png

重啟docker服務

注意:開啟該配置以後,會導致原來下載的映象檔案被隱藏,開啟和關閉該配置情況下的映象檔案是隔離儲存的(OrbStack下驗證)

OrbStack在設定裡面的Docker功能頁新增

Docker Desktop也可以參考https://docs.docker.com/desktop/containerd/

檢視當前構建工具支援的平臺

docker buildx inspect --bootstrap

3.png

其中的Platforms就是當前支援編譯構建的平臺

編譯多平臺映象

編譯指定的多平臺映象載入到本地,平臺之間需使用逗號隔開

docker buildx build --platform linux/amd64,linux/arm64 -t martindai/wechat-robot:1.0 --load .

如果不想把映象載入到本地,想要直接推送到倉庫,修改--load--push即可

檢視映象列表

docker images

4.png

這裡你會發現,有兩個映象檔案,其中第一個就是我們編譯的多平臺映象,檔案大小比較大,而第二個則是適用於當前平臺的映象檔案。

推送到倉庫(確保已經登入)

docker push martindai/wechat-robot:1.0

5.png

可以看到,我們的多平臺映象就完成了。

方法二

我們可以使用命令檢視一下方法一編譯出來的多平臺映象的manifest資訊

docker manifest inspect martindai/wechat-robot:1.0

6.png

可以看到,本質上這個多平臺映象只是一個索引,並不包含實際的檔案,實際背後就是適用於兩個平臺的獨立的映象檔案,docker在使用該映象的時候會解析該索引檔案,然後選擇拉取合適的實際的映象檔案,相當於對於使用者遮蔽了平臺這一層的資訊。

方法一其實就是編譯完多個平臺的映象以後,自動建立了一個索引,然後把各個平臺的映象做了一個關聯。

那麼方法二就是要手動建立這個索引,映象的關聯完全由我們自己控制。

下面開始操作

注意:此方法不能開啟containerd-snapshotter特性

交叉編譯多平臺映象

透過tag區分平臺

docker buildx build --platform linux/amd64 -t martindai/wechat-robot:1.1-amd64 .
docker buildx build --platform linux/arm64 -t martindai/wechat-robot:1.1-arm64 .

或透過映象名區分平臺

docker buildx build --platform linux/amd64 -t martindai/wechat-robot-amd64:1.1 .
docker buildx build --platform linux/arm64 -t martindai/wechat-robot-arm64:1.1 .

PS:下面操作基於tag區分平臺

推送到倉庫

手動關聯的映象必須要在倉庫裡面有才行,所以需要先把編譯好的單平臺映象推送到倉庫

docker push martindai/wechat-robot:1.1-amd64
docker push martindai/wechat-robot:1.1-arm64

7.png

建立manifest關聯映象

docker manifest create martindai/wechat-robot:1.1 martindai/wechat-robot:1.1-amd64 martindai/wechat-robot:1.1-arm64 --amend

確認manifest的資訊

docker manifest inspect martindai/wechat-robot:1.1

8.png

可以看到該manifest跟方法一的manifest是類似的(不是完全一樣,型別其實是不一樣的,只是效果類似),也是關聯了兩個平臺映象。

如果需要修改manifest,可以使用如下命令

docker manifest annotate --arch arm64 martindai/wechat-robot:1.1 martindai/wechat-robot-arm64:1.1

該命令表示,修改martindai/wechat-robot:1.1的manifest的arm64架構關聯的映象為martindai/wechat-robot-arm64:1.1

當然也可以刪除manifest,重新建立

docker manifest rm martindai/wechat-robot:1.1

推送manifest到倉庫

資訊確認沒問題以後,把建立的menifest推送到遠端倉庫

docker manifest push martindai/wechat-robot:1.1

9.png

可以看到倉庫多了一個多平臺映象,並且關聯的就是我們之前上傳的兩個單平臺映象。


總結

方法一使用起來比較方便,也是個人比較推薦的,可以配置在穩定的測試/生產環境使用。

方法二使用起來稍微會麻煩一點,但是會比較靈活,比較適合一些定製化/開發場景。

兩種方法都可以完成建立多平臺映象的工作,具體使用就看個人根據實際情況選擇。

相關文章