
QEMU を使用して、ポータブルなクロスアーキテクチャ Docker コンテナを構築しようとしています。ただし、ホスト システムとホストにインストールされているプログラムに応じて、コンテナの動作が異なります。
Windowsでコンテナを実行すると、エミュレーションは正常に動作します。Ubuntu 16.04でも正常に動作します。いつqemu-user-static がインストールされています。ただし、インストールされていない場合はエミュレーションが停止します。
エミュレーションは、ホスト カーネル (Linux 上の Docker の場合) または VM カーネル (Windows 上の Docker の場合) で binfmt サポートが有効になっていて、必要なバイナリがコンテナーのファイル システムで使用できる限り機能します。
私の目標は、ホスト OS 自体やカーネルへの変更が顧客によって禁止されているため、カーネルに 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 をインストールすると (インストールすると binfmt_misc でも qemu が有効になります)、次のようになります。
$ 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実行可能ファイルのインタープリターとして動的に割り当てられます。
- そうでない場合、実行は失敗し、「実行形式エラー」がスローされます。
- Windows ホスト:
- WindowsとLinuxはカーネルが異なるため、Linuxゲストはシステムコールをホストカーネルに渡して実行することはできません。
- Windowsでは、コンテナは別のカーネルを持つVM内で実行され、そのカーネルはコンテナと共有されます。
- binfmt-support 付きの qemu-user-static が一度インストールされ、任意のコンテナで有効になっている場合、その目的は引き続き果たされ、別のアーキテクチャの実行可能ファイルのインタープリターとして qemu が動的に割り当てられます。
Linux と Windows で実行すると、同等の結果が得られます。
考えられる修正方法は、--privileged フラグを使用してコンテナを起動することです。そうすれば、binfmt_misc をマウントして、コンテナ内のインタープリターとして qemu-user-static を登録できるようになります。しかし、お客様はそのフラグの使用を禁止しています。
私はすでに説明したアプローチをテストしましたここqemu-user の -0 フラグも同様です。どちらも機能しません。
Dockerファイル:
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/
エミュレーションを継続するにはどうすればいいでしょうか?