Archübergreifender Docker-Container beendet die Emulation

Archübergreifender Docker-Container beendet die Emulation

Ich versuche, mit QEMU einen portablen, architekturübergreifenden Docker-Container zu erstellen. Allerdings verhält sich der Container je nach Hostsystem und den darauf installierten Programmen unterschiedlich.

Wenn der Container unter Windows ausgeführt wird, funktioniert die Emulation einwandfrei. Sie funktioniert auch unter Ubuntu 16.04 einwandfrei.Wannqemu-user-static ist installiert. Andernfalls wird die Emulation beendet.

Die Emulation funktioniert, solange die Binfmt-Unterstützung im Host-Kernel (für Docker unter Linux) oder im Kernel der VM (für Docker unter Windows) aktiviert ist UND die erforderlichen Binärdateien im Dateisystem des Containers verfügbar sind.

Mein Ziel ist es, den Container portabel und lauffähig zu machen, ohne dass ich qemu als Interpreter im Kernel registrieren muss, da unser Kunde jegliche Änderungen am Host-Betriebssystem selbst oder seinem Kernel untersagt. Aber derzeit ist das das Ergebnis der Ausführung des Containers:

$ 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

Wenn ich jedoch qemu-user-static installiere (qemu wird durch die Installation auch in binfmt_misc aktiviert):

$ 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

Meine Erklärung dafür ist:

  • qemu-aarch64-static beginnt mit der Emulation von /bin/bash
  • /bin/bash verwendet execve(..), um einige andere ausführbare Dateien aufzurufen
  • Linux-Host:
    • Wenn binfmt_misc entweder vom Host oder vom Container aktiviert wird (unter Linux teilen sich der Host und der Docker-Gast einen Kernel), wird qemu dynamisch als Interpreter für die arm64-ausführbaren Dateien zugewiesen.
    • Andernfalls schlägt die Ausführung fehl und es wird ein „Exec-Formatfehler“ ausgegeben.
  • Windows-Host:
    • Da Windows und Linux unterschiedliche Kernel haben, können Linux-Gäste nicht durch Übergeben von Systemaufrufen an den Host-Kernel ausgeführt werden.
    • Unter Windows laufen Container also in einer VM mit einem separaten Kernel; dieser Kernel wird dann mit den Containern geteilt
    • Wenn qemu-user-static mit binfmt-Unterstützung einmal installiert und in einem beliebigen Container aktiviert wurde, wird es weiterhin seinen Zweck erfüllen und qemu dynamisch als Interpreter für ausführbare Dateien einer anderen Architektur zuweisen.

Die Ausführung unter Linux und Windows liefert gleichwertige Ergebnisse.

Eine mögliche Lösung wäre, den Container mit dem Flag --privileged zu starten. Dann könnte ich binfmt_misc mounten und dadurch qemu-user-static als Interpreter im Container registrieren. Unser Kunde verbietet jedoch die Verwendung dieses Flags.

Ich habe den beschriebenen Ansatz bereits getestetHiersowie das Flag -0 des QEMU-Benutzers. Keines von beiden funktioniert.

Docker-Datei:

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 stammt aus /usr/bin/qemu-aarch64-static (installiert mit qemu-user-static). xenial-arm64-rootfs wird erstellt mit:

qemu-debootstrap --arch=arm64 --components=main,universe,multiverse,restricted --variant=buildd --foreign xenial xenial-arm64-rootfs http://ports.ubuntu.com/ubuntu-ports/

Was kann ich tun, um die Emulation aufrechtzuerhalten?

verwandte Informationen