
我正在嘗試使用 QEMU 建立一個便攜式跨架構 Docker 容器。但是,根據主機系統和主機上安裝的程序,容器的行為有所不同。
在 Windows 上執行容器,模擬運作正常。它在 Ubuntu 16.04 上也運作良好什麼時候qemu-user-static 已安裝。但如果不是,它將停止模擬。
只要在主機核心(對於 Linux 上的 Docker)或虛擬機核心(對於 Windows 上的 Docker)中啟用了 binfmt 支持,並且容器檔案系統中提供了必要的二進位文件,模擬就可以工作。
我的目標是使容器可移植且可運行,而無需將 qemu 註冊為核心中的解釋器,因為我們的客戶禁止對主機作業系統本身或其核心進行任何修改。但目前,這是運行容器的結果:
$ sudo docker run -ti qemu:xenial_arm64
qemu-aarch64-static: /usr/bin/groups: cannot execute binary file: Exec format error
/usr/bin/lesspipe: line 28: /usr/bin/basename: cannot execute binary file: Exec format error
/usr/bin/lesspipe: line 282: /usr/bin/dirname: cannot execute binary file: Exec format error
/usr/bin/lesspipe: line 295: [: =: unary operator expected
qemu-aarch64-static: /usr/bin/dircolors: cannot execute binary file: Exec format error
root@41f2795e2569:/# uname -m
qemu-aarch64-static: /bin/uname: cannot execute binary file: Exec format error
但是,如果我安裝 qemu-user-static (透過安裝 qemu 也會在 binfmt_misc 中啟用):
$ sudo apt-get -yqq install qemu-user-static
Selecting previously unselected package qemu-user-static.
(Reading database ... 245713 files and directories currently installed.)
Preparing to unpack .../qemu-user-static_1%3a2.5+dfsg-5ubuntu10.42_amd64.deb ...
Unpacking qemu-user-static (1:2.5+dfsg-5ubuntu10.42) ...
Processing triggers for man-db (2.7.5-1) ...
Setting up qemu-user-static (1:2.5+dfsg-5ubuntu10.42) ...
$ sudo docker run -ti qemu:xenial_arm64
root@7903b45a3c1e:/# uname -m
aarch64
我對此的解釋是:
- qemu-aarch64-static 開始模擬 /bin/bash
- /bin/bash 使用 execve(..) 呼叫其他一些可執行文件
- Linux主機:
- 如果主機或容器啟用了 binfmt_misc(在 Linux 上,主機和 Docker 來賓共用核心),則 qemu 將被動態指派為 arm64 執行檔的解釋器
- 否則,執行將失敗並拋出“Exec format error”
- Windows 主機:
- 由於 Windows 和 Linux 具有不同的內核,因此無法透過將系統呼叫傳遞到主機內核來執行 Linux 用戶端
- 因此,在 Windows 上,容器在具有單獨核心的 VM 內運行;然後該核心與容器共享
- 如果帶有 binfmt-support 的 qemu-user-static 一旦在任何容器中安裝並啟用,它仍然可以達到其目的,並動態地將 qemu 分配為另一個體系結構的可執行檔的解釋器
在 Linux 和 Windows 上執行會產生相同的結果。
一個可能的修復方法是使用 --privileged 標誌啟動容器。然後我就可以掛載 binfmt_misc 並將 qemu-user-static 註冊為容器內的解釋器。但我們的客戶禁止使用該標誌。
我已經測試過所描述的方法這裡以及 qemu-user 的 -0 個標誌。兩者都不起作用。
Dockerfile:
FROM scratch
ADD xenial-arm64-rootfs /
ADD qemu-aarch64-static /usr/bin/qemu-aarch64-static
RUN chmod +x /usr/bin/qemu-aarch64-static
ENTRYPOINT ["/usr/bin/qemu-aarch64-static", "-0", "/usr/bin/qemu-aarch64-static"]
CMD ["/bin/bash"]
qemu-aarch64-static 取自 /usr/bin/qemu-aarch64-static (與 qemu-user-static 一起安裝) xenial-arm64-rootfs 使用下列指令建立:
qemu-debootstrap --arch=arm64 --components=main,universe,multiverse,restricted --variant=buildd --foreign xenial xenial-arm64-rootfs http://ports.ubuntu.com/ubuntu-ports/
我該怎麼做才能讓模擬繼續進行?