天天看點

多平台Docker鏡像建構教程

雲栖号資訊:【 點選檢視更多行業資訊

在這裡您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!

多平台Docker鏡像建構教程

Adrian Mouat被譽為Docker Captain,他是Container Solutions 公司的首席科學家。目前,他正開發 Trow,這是一個容器鏡像注冊中心,用于安全管理 Kubernetes 叢集中的鏡像流。

目前,Docker 鏡像已經成為測試和部署新的第三方軟體的标準工具。Adrian 是開源 Trow 注冊中心的主要開發者,而Docker 鏡像則是人們安裝該工具的主要方式。如果他不提供鏡像,其他人最終也會推出他們自己的鏡像,這樣會導緻重複"造輪子”,并産生維護問題。

預設情況下,我們建立的Docker 鏡像運作在 linux/amd64 平台上。它适用于大多數的開發機器和雲提供商,但卻忽略其他平台的使用者。這個群體很龐大——想想基于樹莓派的家庭實驗室、生産物聯網裝置的公司、運作在 IBM 大型機上的組織以及使用低功耗 arm64 晶片的雲。

一般來說,這些平台的使用者通常會建構自己的鏡像或尋找其他解決方案。

那麼,你該如何為這些平台建構鏡像?最明顯的方法是在目标平台上建構鏡像。這适用于很多情況。但是如果你的目标是 s390x,我希望你有可以使用的 IBM 大型機。更常見的平台,比如樹莓派、物聯網裝置通常電量有限,速度慢或無法建構鏡像。

我們該怎麼做?有兩個選項:1. 目标平台仿真,2. 交叉編譯。有趣的是,我發現有種方法可以将這兩個選項結合的效果最好。

1.仿真

讓我們從第一個選項——仿真開始。有一個很不錯的項目叫 QEMU,它可以模拟很多平台。随着最近 buildx 的預覽,将 QEMU 用于 Docker 變得更加容易。

https://www.qemu.org/ https://github.com/docker/buildx

QEMU 內建依賴于一個 Linux 核心特性,該特性有個稍顯神秘的名字 binfmt_misc handler。當 Linux 遇到其無法識别的可執行檔案格式(例如,一個用于不同體系結構的檔案格式)時,它将使用該處理程式檢查是否配置了什麼“使用者空間應用程式”來處理該格式(例如,模拟器或 VM)。如果有,它将把可執行檔案傳遞給該應用程式。

為實作這一點,我們需要在核心中注冊我們關注的平台。如果你正在使用 Docker Desktop,那麼對于大多數常見平台,你就無需做這項工作。如果你正使用 Linux,你可以通過運作最新的docker/binfmt鏡像,以與 Docker Desktop 相同的方式注冊處理程式,例如:

docker run --privileged --rm docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64           

完成此操作後,你可能需要重新開機 Docker。如果你想要對自己想注冊的平台有更多控制或想使用更高深莫測的平台(例如 PowerPC),請檢視 qus 項目。

https://github.com/dbhi/qus

Buildx 有兩種不同的用法,但最簡單的方法可能是在 Docker CLI 上啟用實驗性特性(如果你還沒有這樣做的話),編輯~/.docker/config.json檔案,使其包含以下内容:

{
    ...
     "experimental": “enabled”
}           

你現在應該能運作docker buildx ls,并得到類似以下的輸出:

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

讓我們為另一個平台建構一個鏡像,從 Dockerfile 開始:

FROM debian:buster
CMD uname -m           

如果我們正常建構,運作以下指令:

$ docker buildx build -t local-build .
…
$ docker run --rm local-build
x86_64           

但是,如果我們顯式指定建構針對的平台,則執行以下指令:

$ docker buildx build --platform linux/arm/v7 -t arm-build .
…
$ docker run --rm arm-build
armv7l           

成功!我們已經成功地在 x86_64 筆記本上建構和運作了 armv7 鏡像,并且隻做了很少工作。這種技術很有效,但對于更複雜的建構,你可能會發現它運作太慢,或者遇到 QEMU 中的 Bug。在這些情況下,有必要研究一下是否可以交叉編譯你的鏡像。

2.交叉編譯

一些編譯器能為 foreign platforms 生成二進制代碼,最著名的包括 Go 和 Rust。通過 Trow 注冊中心項目,我們發現,交叉編譯是為其他平台建立鏡像最快、最可靠的方法。例如,這裡是 Trow armv7 鏡像的 Dockerfile。

https://github.com/ContainerSolutions/trow/blob/master/docker/Dockerfile.armv7

最重要的一行是:

RUN cargo build --target armv7-unknown-linux-gnueabihf -Z unstable-options --out-dir ./out           

它明确告訴 Rust,我們希望二進制檔案在哪個平台上運作。然後,我們可以使用多級建構将這個二進制檔案複制到目标體系結構的基本鏡像中(如果是靜态編譯,也能使用 scratch),這樣就完成了。然而,對于 Trow 注冊中心,我想在最終的鏡像中設定更多東西,是以最後階段實際上開始于:

FROM --platform=linux/arm/v7 debian:stable-slim           

是以,我實際上混合使用了仿真和交叉編譯——交叉編譯用來建立二進制檔案,仿真用來運作和配置最終的鏡像。

3.清單清單

在上面關于仿真的建議中,你可能已經注意到:我們使用--platform參數來設定建構平台,但是我們在 FROM 行中将鏡像指定為 debian:buster。這看起來似乎沒有意義——平台當然依賴于基本鏡像以及它是如何建構的,而不是使用者之後的決定。

這樣做是因為 Docker 使用了一種叫做清單清單的東西。對于給定鏡像,這些清單包含指向不同體系結構鏡像的指針。因為官方的 debian 鏡像有一個定義好的清單清單,當我在筆記本上拉取這個鏡像時,我會自動獲得 amd64 鏡像,當我在樹莓派上拉取它時,我将得到 armv7 鏡像。

為了讓使用者滿意,我們可以為自己的鏡像建立清單。如果我們回到前面的例子,首先我們需要重新建構并将鏡像推送到一個鏡像庫:

$ docker buildx build --platform linux/arm/v7 -t amouat/arch-test:armv7 .
…
$ docker push amouat/arch-test:armv7
…
$ docker buildx build -t amouat/arch-test:amd64 .
…
$ docker push amouat/arch-test:amd64           

接下來,我們建立一個清單清單指向這兩個單獨的鏡像,并推送它們:

$ docker manifest create amouat/arch-test:blog amouat/arch-test:amd64 amouat/arch-test:armv7
Created manifest list docker.io/amouat/arch-test:blog
$ docker manifest push amouat/arch-test:blog
sha256:039dd768fc0758fbe82e3296d40b45f71fd69768f21bb9e0da02d0fb28c67648           

現在,Docker 将拉取并運作适合目前平台的鏡像:

$ docker run amouat/arch-test:blog
Unable to find image 'amouat/arch-test:blog' locally
blog: Pulling from amouat/arch-test
Digest: sha256:039dd768fc0758fbe82e3296d40b45f71fd69768f21bb9e0da02d0fb28c67648
Status: Downloaded newer image for amouat/arch-test:blog
x86_64           

有樹莓派的讀者可以試着運作這個鏡像,并确認它确實能在那個平台上工作!回顧一下:并不是 Docker 鏡像的所有使用者都運作 amd64。使用 buildx 和 QEMU,隻需額外少量工作就可以為這些使用者提供支援。

【雲栖号線上課堂】每天都有産品技術專家分享!

課程位址:

https://yqh.aliyun.com/live

立即加入社群,與專家面對面,及時了解課程最新動态!

【雲栖号線上課堂 社群】

https://c.tb.cn/F3.Z8gvnK

原文釋出時間:2020-04-14

本文作者:Adrian Mouat

本文來自:“

InfoQ 微信公衆号

”,了解相關資訊可以關注“

InfoQ

繼續閱讀