
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?