O contêiner Docker de arco cruzado interromperá a emulação

O contêiner Docker de arco cruzado interromperá a emulação

Estou tentando construir um contêiner Docker de arco cruzado portátil usando QEMU. No entanto, dependendo do sistema host e dos programas instalados no host, o contêiner se comporta de maneira diferente.

Executando o contêiner no Windows, a emulação funciona bem. Também funciona bem no Ubuntu 16.04quandoqemu-user-static está instalado. Mas deixará de emular se não for.

A emulação funciona desde que o suporte binfmt esteja habilitado no kernel Host (para Docker no Linux) ou no kernel da VM (para Docker no Windows) E os binários necessários estejam disponíveis no sistema de arquivos dos contêineres.

Meu objetivo é tornar o contêiner portátil e executável sem a necessidade de registrar o qemu como intérprete no kernel, uma vez que quaisquer modificações no próprio sistema operacional Host ou em seu kernel são proibidas pelo nosso cliente. Mas atualmente, esse é o resultado da execução do contêiner:

$ 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

No entanto, se eu instalar o qemu-user-static (o qemu também será habilitado em binfmt_misc ao instalá-lo):

$ 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

Minha explicação para isso é:

  • qemu-aarch64-static começa a emular /bin/bash
  • /bin/bash usa execve(..) para chamar alguns outros executáveis
  • Hospedeiro Linux:
    • se binfmt_misc estiver habilitado pelo host ou pelo contêiner (no Linux, o host e o convidado do Docker compartilham um kernel), o qemu será atribuído dinamicamente como um intérprete para os executáveis ​​​​arm64
    • caso contrário, a execução falhará e "Exec format error" será lançado
  • Hospedeiro do Windows:
    • como o Windows e o Linux têm kernels diferentes, os convidados do Linux não podem ser executados passando syscalls para o kernel do host
    • assim, no Windows, os contêineres são executados dentro de uma VM com um kernel separado; esse kernel é então compartilhado com os contêineres
    • se qemu-user-static com binfmt-support já foi instalado e habilitado em qualquer contêiner, ele ainda servirá ao seu propósito e atribuirá dinamicamente o qemu como intérprete para executáveis ​​​​de outra arquitetura

A execução no Linux e no Windows produz resultados equivalentes.

Uma possível solução seria iniciar o contêiner usando o sinalizador --privileged. Então eu seria capaz de montar binfmt_misc e, assim, registrar qemu-user-static como um intérprete dentro do contêiner. Mas nosso cliente proíbe usar essa bandeira.

Eu já testei a abordagem descritaaquibem como o sinalizador -0 do qemu-user. Nenhum dos dois funciona.

Arquivo 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 é obtido de /usr/bin/qemu-aarch64-static (instalado com qemu-user-static) xenial-arm64-rootfs é criado usando:

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

O que posso fazer para manter a emulação?

informação relacionada