El contenedor Docker de arco cruzado detendrá la emulación

El contenedor Docker de arco cruzado detendrá la emulación

Estoy intentando construir un contenedor Docker de arco cruzado portátil usando QEMU. Sin embargo, dependiendo del sistema host y de los programas instalados en el host, el contenedor se comporta de manera diferente.

Al ejecutar el contenedor en Windows, la emulación funciona bien. También funciona bien en Ubuntu 16.04cuandoqemu-user-static está instalado. Pero dejará de emular si no es así.

La emulación funciona siempre que binfmt-support esté habilitado en el kernel del host (para Docker en Linux) o en el kernel de la VM (para Docker en Windows) Y los binarios necesarios estén disponibles en el sistema de archivos de los contenedores.

Mi objetivo es hacer que el contenedor sea portátil y ejecutable sin la necesidad de registrar qemu como intérprete en el kernel, ya que nuestro cliente prohíbe cualquier modificación en el sistema operativo Host o en su kernel. Pero actualmente, ese es el resultado de ejecutar el contenedor:

$ 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

Sin embargo, si instalo qemu-user-static (qemu también se habilitará en binfmt_misc al instalarlo):

$ 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

Mi explicación para eso es:

  • qemu-aarch64-static comienza a emular /bin/bash
  • /bin/bash usa execve(..) para llamar a otros ejecutables
  • Anfitrión Linux:
    • Si binfmt_misc está habilitado por el host o por el contenedor (en Linux, el host y el invitado de Docker comparten un kernel), qemu se asignará dinámicamente como intérprete para los ejecutables de arm64.
    • de lo contrario, la ejecución fallará y se generará un "Error de formato de ejecución".
  • Anfitrión de Windows:
    • Dado que Windows y Linux tienen kernels diferentes, los invitados de Linux no se pueden ejecutar pasando llamadas al sistema al kernel del host.
    • en Windows, los contenedores se ejecutan dentro de una VM con un kernel separado; ese kernel luego se comparte con los contenedores
    • Si qemu-user-static con binfmt-support alguna vez estuvo instalado y habilitado en cualquier contenedor, seguirá cumpliendo su propósito y asignará dinámicamente qemu como intérprete para ejecutables de otra arquitectura.

La ejecución en Linux y en Windows produce resultados equivalentes.

Una posible solución sería iniciar el contenedor usando el indicador --privileged. Entonces podría montar binfmt_misc y así registrar qemu-user-static como intérprete dentro del contenedor. Pero nuestro cliente prohíbe usar esa bandera.

Ya probé el enfoque descrito.aquíasí como el indicador -0 de qemu-user. Ninguno de los dos funciona.

Archivo 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 se toma de /usr/bin/qemu-aarch64-static (instalado con qemu-user-static) xenial-arm64-rootfs se crea usando:

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

¿Qué puedo hacer para mantener la emulación?

información relacionada