Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
technique:docker:general:quemu_cross_running [2021/01/21 11:34] – Fixed embeded code formating gblondtechnique:docker:general:quemu_cross_running [2021/10/16 18:19] (Version actuelle) qduchemi
Ligne 1: Ligne 1:
 {{indexmenu_n>70}} {{indexmenu_n>70}}
  
-# QEMU : Utiliser des conteneurs avec une architecture a priori incompatible avec l'hôte+# QEMU : utiliser une architecture incompatible avec l'hôte 
 + 
 +<bootnote warning> 
 +Cet article est très spécifique, vous n'avez probablement pas besoin de le lire si vous voulez découvrir Docker! 
 +</bootnote> 
 Saviez-vous que l'utilisation conjointe de Docker et QEMU permet d'utiliser par exemple un conteneur ARMv7 sur un hôte x86-AMD64 de manière (presque) totalement transparente ? Non vous ne rêvez pas, c'est même très simple à mettre en place ! Saviez-vous que l'utilisation conjointe de Docker et QEMU permet d'utiliser par exemple un conteneur ARMv7 sur un hôte x86-AMD64 de manière (presque) totalement transparente ? Non vous ne rêvez pas, c'est même très simple à mettre en place !
  
Ligne 16: Ligne 21:
 <bootnote question>Mais pourquoi aurait-on besoin de mélanger ces architectures ?</bootnote> <bootnote question>Mais pourquoi aurait-on besoin de mélanger ces architectures ?</bootnote>
  
-Il y a plusieurs cas d’utilisation où il est utile émuler un microprocesseur différent de celui de la machine hôte, notamment durant des phases de développement ou de test d’un programme. Imaginez que vous développez un gros logiciel compilé pour des Raspberry Pi, architecture ARMv7, mais que votre poste de travail est équipé d’un microprocesseur x86-AMD64. Il y a alors 4 manières de compiler ce programme :+Il y a plusieurs cas d’utilisation où il est utile d’émuler un microprocesseur différent de celui de la machine hôte, notamment durant des phases de développement ou de test d’un programme. Imaginez que vous développez un gros logiciel compilé pour des Raspberry Pi, architecture ARMv7, mais que votre poste de travail est équipé d’un microprocesseur x86-AMD64. Il y a alors 4 manières de compiler ce programme :
  
   * Compiler depuis une Raspberry Pi : cette solution fonctionne pour des petits projets, mais montre rapidement ses limites en matières de ressources matérielles disponibles (surtout la RAM), et est en général la plus lente des 4 solutions ;   * Compiler depuis une Raspberry Pi : cette solution fonctionne pour des petits projets, mais montre rapidement ses limites en matières de ressources matérielles disponibles (surtout la RAM), et est en général la plus lente des 4 solutions ;
Ligne 42: Ligne 47:
 <code> <code>
  $ docker run --rm --priviledged multiarch/qemu-user-static --reset -p yes  $ docker run --rm --priviledged multiarch/qemu-user-static --reset -p yes
-Status: Downloaded newer image for multiarch/qemu-user-static:latest 
 Setting /usr/bin/qemu-alpha-static as binfmt interpreter for alpha Setting /usr/bin/qemu-alpha-static as binfmt interpreter for alpha
 Setting /usr/bin/qemu-arm-static as binfmt interpreter for arm Setting /usr/bin/qemu-arm-static as binfmt interpreter for arm
Ligne 50: Ligne 54:
 </code> </code>
  
-Veuillez noter la présence de l'option ''--privileged'' qui permet au conteneur d'interagir avec le système hôte. L'option ''--reset'' demande au script de remplacer les exécutables s'ils existent déjà, et ''-p'' yes les persiste lorsque le conteneur se ferme.+Veuillez noter la présence de l'option ''--privileged'' qui permet au conteneur d'interagir avec le système hôte. L'option ''--reset'' demande au script de remplacer les exécutables s'ils existent déjà, et ''-p yes'' les persiste lorsque le conteneur se ferme. 
 + 
 +<bootnote warning> 
 +Cette commande est à exécuter à chaque fois que le démon docker est redémarré (typiquement quand la machine hôte redémarre). 
 +</bootnote>
  
 Le script a ajouté les interpréteurs dans le dossier virtuel ''/proc/sys/fs/binfmt_misc/'' de la machine hôte. On peut vérifier leur activation : Le script a ajouté les interpréteurs dans le dossier virtuel ''/proc/sys/fs/binfmt_misc/'' de la machine hôte. On peut vérifier leur activation :
Ligne 63: Ligne 71:
 mask ffffffffffffff00fffffffffffffffffeffffff mask ffffffffffffff00fffffffffffffffffeffffff
 </code> </code>
 +
 +Cette méthode a l'avantage de ne pas nécessiter d'installer des paquets supplémentaires sur la machine hôte. Mais tout ce qui suit est tout-à-fait valable si vous avez installé qemu en global (''apt install qemu-user-static'').
  
 ### Exécuter un conteneur d’une architecture incompatible ### Exécuter un conteneur d’une architecture incompatible
 +
 +Comme indiqué dans l'introduction, ici rien ne change, on peut utiliser docker normalement. Enfin presque, car docker sélectionnera toujours l'architecture hôte pour une image disponible avec plusieurs architecture. Pour sélectionner l'architecture voulue, il faut utiliser l'option ''--platform=linux/arm64''. À ce jour (docker v19.03.13), cette option n'est disponible que en [[https://docs.docker.com/engine/reference/commandline/dockerd/#description | mode experimental]].
 +
 +Voici un exemple d'exécution :
 +
 +<code>
 +$ uname -a
 +Linux gaetan-PC 5.8.0-38-generic #43-Ubuntu SMP Tue Jan 12 12:42:13 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
 +$ docker run --rm -it arm32v7/alpine uname -a
 +Linux fcee9f02cc9a 5.8.0-38-generic #43-Ubuntu SMP Tue Jan 12 12:42:13 UTC 2021 armv7l Linux
 +$ docker run --rm -it arm64v8/alpine ls         
 +bin    etc    lib    mnt    proc   run    srv    tmp    var
 +dev    home   media  opt    root   sbin   sys    usr
 +</code>
 +
 +<bootnote>
 +Si vous obtenez l'erreur
 +
 +<code>
 +standard_init_linux.go:211: exec user process caused "exec format error"
 +</code>
 +c’est que vous avez oublié de configurer qemu !
 +</bootnote>
 +
 +À partir de maintenant, il est possible d'utiliser une image docker contenant un compilateur d'une autre architecture pour effectuer de la cross-compilation. Mais on peut encore aller plus loin : créer une image pour une autre architecture !
  
 ### Créer un conteneur pour une architecture incompatible ### Créer un conteneur pour une architecture incompatible
 +
 +De même que pour l'exécution, en cas d'ambiguïté sur l'architecture d'une image, Docker sélectionnera toujours celle de l'architecture hôte. Ainsi, il n'est pas possible de commencer une image avec
 +
 +<code dockerfile>
 +FROM scratch
 +</code>
 +
 +Cependant, on peut préciser une image exclusivement disponible pour l'architecture souhaitée, puis continuer à la construire comme on construirait une image normale. Il est aussi autorisé de mélanger les architectures — à vos risques et périls — pour une image //multi-stage//. Par exemple,
 +
 +<code dockerfile Dockerfile>
 +FROM alpine as first_stage
 +
 +RUN uname -a > /uname1.txt
 +
 +FROM arm64v8/busybox
 +
 +COPY --from=first_stage /uname1.txt /uname1.txt
 +
 +CMD echo "First stage: " && cat /uname1.txt && echo "Last stage: " && uname -a
 +</code>
 +
 +on obtient alors par exemple ces résultats :
 +
 +<code bash>
 +$ docker build -t test_docker .  
 +Sending build context to Docker daemon  2.048kB
 +Step 1/5 : FROM alpine as first_stage
 + ---> 7731472c3f2a
 +Step 2/5 : RUN uname -a > /uname1.txt
 + ---> Using cache
 + ---> 7d147fe81388
 +Step 3/5 : FROM arm64v8/busybox
 + ---> bffe63f0059e
 +Step 4/5 : COPY --from=first_stage /uname1.txt /uname1.txt
 + ---> Using cache
 + ---> 0b7ea3dd5953
 +Step 5/5 : CMD echo "First stage: " && cat /uname1.txt && echo "Last stage: " && uname -a
 + ---> Running in 33ffd9407823
 +Removing intermediate container 33ffd9407823
 + ---> b76215700cbb
 +Successfully built b76215700cbb
 +Successfully tagged test_docker:latest
 +
 +$ docker run --rm -it test_docker                                       
 +First stage: 
 +Linux cd2527490809 5.8.0-38-generic #43-Ubuntu SMP Tue Jan 12 12:42:13 UTC 2021 x86_64 Linux
 +Last stage: 
 +Linux 211b99ac36e4 5.8.0-38-generic #43-Ubuntu SMP Tue Jan 12 12:42:13 UTC 2021 aarch64 GNU/Linux
 +</code>
 +
 +De même, il est possible d'utiliser l'option ''--platform=linux/arm64'' dans l'instruction ''FROM'' si docker est en mode experimental.
 +
 +<bootnote important>
 +Suivant les clients dockers, il est possible que l'architecture indiquée dans l'image ne corresponde pas à celle réelle ; dans ce cas vous pourriez par mégarde écraser une image de l'architecture hôte au moment de pousser l'image sur un serveur multi-arch !
 +
 +Pour connaître l'architecture que docker a associé avec une image, on peut utiliser la commande suivante :
 +
 +<code bash>
 +$ docker inspect test_docker | grep Architecture
 +        "Architecture": "arm64",
 +</code>
 +
 +</bootnote>
 +
 +<bootnote>
 +En théorie, rien ne vous interdit de copier un binaire d'une architecture A dans une image d'une architecture B. Cependant, vous ne pourrez pas l'exécuter, même si qemu est configuré sur la machine hôte.
 +</bootnote>
  • technique/docker/general/quemu_cross_running.1611225291.txt.gz
  • de gblond