建立 Docker 多架構 image (Building Docker multi-arch image)
最近練習用 Python 寫了一個小機器人,機器人在背景執行、無對外服務、不需 root 權限,最初在 x86 Linux 虛擬機內開發,最近想遷移到樹莓派上。
該機器人需要 TA-Lib,且需要從原始碼編譯,如果佈署至多台 Raspberry Pi 就會花很多工時在編譯上。因此靈機一動,不如將 Python 3.9 + TA-Lib 的環境打包成 Docker image 並發佈到 Docker Hub。
再靈機一動,不如弄成 multi-arch,以後還可以放到 x86 的 NAS 上。
Docker 有兩種方法可以建立 multi-arch image:manifest 以及 Buildx,我在 Docker 官網第一眼看到的教學是 Buildx 進行,因此使用它。
兩種工具的用法在網路上有很多文章可參考,如:
Multi-Architecture镜像制作指南已到,请查收! — 知乎 (zhihu.com)
使用 buildx 构建多种系统架构支持的 Docker 镜像 — Docker — — 从入门到实践 (gitbook.io)
Docker build x86/ARM multi-arch images with AWS ECR — Mr. 沙先生 (shazi.info)
我的建置環境為一台 搭載 Intel J3060 的小電腦,執行 Ubuntu 20.04 x64,build 之前有先更新至最新版 Docker,過舊的 Docker 可能會遭遇找不到 Buildx 的情況。
照著 tutorial 建立並切換到一個新的 builder
$ docker buildx create --name mybuilder && docker buildx use mybuilder
開始建置 image,我選擇建立 amd64 & arm64 & arm/v7 版本的
$ docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t latest
原本以為照著教學走就能將建置好的 image push 到 Docker Hub 上,但實際在 build ARM 架構的 image 遇到下列問題:
> [linux/arm/v7 3/6] RUN pip install cython && ln -s /usr/include/locale.h /usr/include/xlocale.h && pip install numpy:
...................略...................
#14 97.02 File "/usr/local/lib/python3.9/subprocess.py", line 528, in run
#14 97.03 raise CalledProcessError(retcode, process.args,
#14 97.03 subprocess.CalledProcessError: Command '('lsb_release', '-a')' returned non-zero exit status 1.
無法執行 lsb_release
?
找了相關 issue ,看到一句話:
“If error happens on running a specific process only under emulation it is likely the emulation layer (qemu) that has the issue on executing this specific code. Just make sure that your nodes have emulators installed properly.”
看來是 QEMU 環境沒正確設定起來,在 tonistiigi/binfmt (github.com) 可以找到工具協助安裝,執行下列指令:
docker run --privileged --rm tonistiigi/binfmt --install all
(參考 error in python3.9 pip install via qemu for arm64 · Issue #493 · docker/buildx (github.com))
安裝完 QEMU,再次呼叫 Buildx 建置 image,沒問題了。
開始漫長的等待...