使用 buildx 構建多平臺 Docker 映象
原文連結:使用 buildx 構建多平臺 Docker 映象
在工作和生活中,我們可能經常需要將某個程式跑在不同的 CPU 架構上,比如讓某些不可描述的軟體執行在樹莓派或嵌入式路由器裝置上。特別是 Docker 席捲全球之後,我們可以輕鬆地在 ARM 裝置上通過容器部署各種好玩的應用,而不用在意各種系統的差異性。
但是想要跨平臺構建 Docker 映象可不是一件輕鬆的活,要麼到不同 CPU 架構的系統上全部構建一遍,要麼就得在當前系統上通過虛擬化技術模擬不同的 CPU 架構,最後可能還要想辦法合併映象,費力不討好。
不過值得慶幸的是,Docker 19.03
引入了一個新的實驗性外掛,該外掛使得跨平臺構建 Docker 映象比以往更加容易了。在介紹這個新特性之前,我們先來了解一下跨 CPU 架構構建程式的基礎知識。
1. 跨 CPU 架構編譯程式的方法
先來快速回顧一下當前跨 CPU 架構編譯程式的不同方法。
方法一:直接在目標硬體上編譯
如果你能夠訪問目標 CPU 架構的系統,並且該作業系統支援執行構建所需的各種工具,那麼你可以直接在目標系統上編譯程式。
以構建 Docker 映象為例,你可以在樹莓派上安裝 Docker,然後在樹莓派上通過 Dockerfile
直接構建 arm 平臺的映象。
如果無法訪問目標 CPU 架構的系統該怎麼辦?有沒有辦法通過某種方式直接在當前系統上構建目標 CPU 架構的程式?請看下文...
方法二:模擬目標硬體
還記得我們小時候在各種網吧檯球室之類的場合玩的街機遊戲嗎?放張圖給你們回憶一下:
如果現在我們想重新體驗以前玩過的街機遊戲該怎麼辦?這時候就需要用到模擬器(Emulator)了。藉助模擬器,我們可以讓時光倒流,體驗經典遊戲的樂趣。
模擬器除了可以用來玩遊戲之外,還可以用來跨 CPU 架構構建程式。最常用的模擬器是開源的 QEMU,QEMU 支援許多常見的 CPU 架構,包括 ARM
、Power-PC
和 RISC-V
等。通過模擬一個完整的作業系統,可以建立通用的 ARM 虛擬機器,該虛擬機器可以引導 Linux,設定開發環境,也可以在虛擬機器內編譯程式。
然而,模擬整個作業系統還是有點浪費,因為在這種模式下,QEMU 將會模擬整個系統,包括計時器、記憶體控制器、匯流排控制器等硬體。但編譯程式根本不需要關心這些,還可以再精簡些。
方法三:通過 binfmt_misc 模擬目標硬體的使用者空間
在 Linux 上,QEMU
除了可以模擬完整的作業系統之外,還有另外一種模式叫使用者態模式
(User mod)。該模式下 QEMU 將通過 binfmt_misc 在 Linux 核心中註冊一個二進位制轉換處理程式,並在程式執行時動態翻譯二進位制檔案,根據需要將系統呼叫從目標 CPU 架構轉換為當前系統的 CPU 架構。最終的效果看起來就像在本地執行目標 CPU 架構的二進位制檔案。
通過 QEMU 的使用者態模式,我們可以建立輕量級的虛擬機器(chroot 或容器),然後在虛擬機器系統中編譯程式,和本地編譯一樣簡單輕鬆。後面我們就會看到,跨平臺構建 Docker 映象用的就是這個方法。
方法四:使用交叉編譯器
最後介紹一種嵌入式系統社群常用的方法:交叉編譯(cross-compilation)。
交叉編譯器是專門為在給定的系統平臺上執行而設計的編譯器,但是可以編譯出另一個系統平臺的可執行檔案。例如,amd64
架構的 Linux 系統上的 C++ 交叉編譯器可以編譯出執行在 aarch64
(64-bit ARM) 架構的嵌入式裝置上的可執行檔案。再舉個真實的例子,安卓裝置的 APP 基本上都是通過這種方法來編譯的。
從效能角度來看,該方法與方法一沒什麼區別,因為不需要模擬器的參與,幾乎沒有效能損耗。但交叉編譯不具有通用性,它的複雜度取決於程式使用的語言,如果使用 Golang 的話,那就超級容易了。
在全民容器時代,我們討論構建時不僅包括構建單個可執行檔案,還包括構建容器映象。而且構建容器映象比上面說的方法更復雜,再加上 Docker 本身的複雜性,這幾乎是一個老大難的問題。
但引入了新的實驗性外掛之後,構建多平臺架構的 Docker 映象就比以前容易多了,至於這個外掛到底是啥,下文會詳細介紹。
2. 構建多平臺 Docker 映象
利用 Docker 19.03 引入的外掛 buildx,可以很輕鬆地構建多平臺 Docker 映象。buildx 是 docker build ...
命令的下一代替代品,它利用 BuildKit 的全部功能擴充套件了 docker build
的功能。
下面就來演示一下如何在短短几分鐘內使用 buildx
構建出不同平臺的 Docker 映象。步驟如下:
啟用 buildx 外掛
要想使用 buildx
,首先要確保 Docker 版本不低於 19.03
,同時還要通過設定環境變數 DOCKER_CLI_EXPERIMENTAL
來啟用。可以通過下面的命令來為當前終端啟用 buildx 外掛: