Контейнер Docker Cross-arch остановит эмуляцию

Контейнер Docker Cross-arch остановит эмуляцию

Я пытаюсь создать переносимый кросс-архитектурный Docker-контейнер с использованием QEMU. Однако в зависимости от хост-системы и программ, установленных на хосте, контейнер ведет себя по-разному.

Запускаем контейнер на Windows, эмуляция работает отлично. Также отлично работает на Ubuntu 16.04когдаqemu-user-static установлен. Но если его нет, то эмуляция прекратится.

Эмуляция работает до тех пор, пока включена поддержка binfmt в ядре хоста (для Docker на Linux) или в ядре виртуальной машины (для Docker на Windows) И необходимые двоичные файлы доступны в файловой системе контейнера.

Моя цель — сделать контейнер переносимым и запускаемым без необходимости регистрации qemu как интерпретатора в ядре, поскольку любые изменения в самой Host-OS или ее ядре запрещены нашим заказчиком. Но в настоящее время это результат запуска контейнера:

$ 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».
  • Хост Windows:
    • Поскольку Windows и Linux имеют разные ядра, гостевые системы Linux не могут быть запущены путем передачи системных вызовов ядру хоста.
    • поэтому в Windows контейнеры работают внутри виртуальной машины с отдельным ядром; это ядро ​​затем используется совместно с контейнерами
    • если qemu-user-static с binfmt-support был однажды установлен и включен в любом контейнере, он все равно будет выполнять свою задачу и динамически назначать qemu в качестве интерпретатора для исполняемых файлов другой архитектуры

Выполнение в Linux и Windows дает эквивалентные результаты.

Возможным решением будет запуск контейнера с использованием флага --privileged. Тогда я смогу смонтировать binfmt_misc и тем самым зарегистрировать qemu-user-static как интерпретатор внутри контейнера. Но наш клиент запрещает использовать этот флаг.

Я уже опробовал описанный подход.здесьа также флаг -0 у qemu-user. Ни один из них не работает.

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/

Что я могу сделать, чтобы эмуляция продолжалась?

Связанный контент