2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
buildx est un outil de construction officiellement fourni par Docker. Il peut aider les utilisateurs à créer des images Docker rapidement et efficacement et prend en charge la construction de plusieurs plates-formes. Grâce à buildx, les utilisateurs peuvent créer des images pour plusieurs architectures, telles que les architectures x86 et arm, en une seule commande sans avoir à exécuter manuellement plusieurs commandes de construction. De plus, buildx prend également en charge la construction en plusieurs étapes et la mise en cache de Dockerfile, ce qui peut considérablement améliorer l'efficacité et la vitesse de construction d'images.
buildx est un plug-in CLI qui gère les builds Docker. La couche sous-jacente utilise BuildKit pour étendre les capacités de build Docker.
BuildKit est un moteur de build hautes performances officiellement fourni par Docker, qui peut être utilisé pour remplacer le moteur de build d'origine de Docker. Par rapport au moteur d'origine, BuildKit a une vitesse de construction plus rapide, un parallélisme plus élevé, une utilisation moindre des ressources et une meilleure sécurité.
Pour installer et utiliser buildx, le numéro de version de Docker Engine est supérieur ou égal à 19.03.
Le constructeur prend en charge différentes stratégies pour créer des images multiplateformes.
Si vous utilisez Docker Desktop, QEMU est déjà pris en charge et constitue la stratégie la plus simple pour créer des images multiplateformes. Il ne nécessite aucune modification du Dockerfile d'origine. BuildKit implémentera l'exécution du programme multiplateforme via la fonction binfmt_misc du noyau Linux.
principe de fonctionnement:
QEMU est un simulateur de processeur qui peut simuler différentes architectures de processeur. Nous pouvons le comprendre comme une autre forme de machine virtuelle. Dans buildx, QEMU est utilisé pour exécuter des binaires pour les architectures non natives pendant le processus de construction. Par exemple, lors de la création d'une image ARM sur un hôte x86, QEMU peut émuler l'environnement ARM et exécuter des binaires ARM.
binfmt_misc est un module du noyau Linux qui permet aux utilisateurs d'enregistrer les formats de fichiers exécutables et les interpréteurs correspondants.Lorsque le noyau rencontre un fichier exécutable de format inconnu, binfmt_misc est utilisé pour trouver l'interpréteur associé au format de fichier (QEMU dans ce cas) et exécuter le fichier. . Cette fonction est désactivée sur la plateforme rk3568.
La combinaison de QEMU et binfmt_misc rend possible la construction multiplateforme via buildx. Cela nous permet de créer des images Docker pour une architecture sur un hôte pour d'autres architectures sans avoir à posséder le matériel cible réel.
Bien que Docker Desktop soit préconfiguré avec la prise en charge de binfmt_misc pour d'autres plates-formes, pour d'autres versions de Docker, vous devrez peut-être utiliser l'image tonistiigi/binfmt pour démarrer un conteneur privilégié à des fins de prise en charge.
docker run --privileged --rm tonistiigi/binfmt --install all
L'exécution de cette commande installera des programmes interpréteurs de différentes architectures, c'est-à-dire le simulateur qemu dans le répertoire /usr/bin :
Le module binfmt_misc est chargé sur notre serveur de compilation :
Docker Buildx est une fonctionnalité expérimentale de Docker qui étend les capacités de construction de Docker, notamment l'utilisation de multi-nœuds, de qemu, etc. QEMU est un logiciel de machine virtuelle open source qui peut simuler différents processeurs et autres matériels, nous permettant de créer une image d'un autre système d'exploitation sur un système d'exploitation.
L'utilisation de la fonction qemu de Docker Buildx peut nous aider à créer des images Docker pour plusieurs architectures différentes (telles que ARM, MIPS, etc.).
Voici un exemple simple montrant comment utiliser Docker Buildx et QEMU pour créer une image Docker pour l'architecture ARM :
- # 创建一个新的 buildkit 实例
- docker buildx create --name mybuilder --use
-
- # 启动 buildkit 实例
- docker buildx start mybuilder
-
- # 启用 QEMU 驱动支持
- docker buildx inspect --bootstrap
-
- # 构建一个面向 ARM 架构的 Docker 镜像
- docker buildx build --platform linux/arm/v7 -t myimage:latest .
Dans cet exemple,--platform
Le paramètre spécifie que la plate-forme cible pour laquelle nous souhaitons créer est ARM v7. De cette façon, Docker utilisera QEMU pour simuler un environnement ARM et créer une image Docker pour l'architecture ARM sur la machine à architecture x86.
binfmt-misc est une fonction fournie par le noyau Linux qui est similaire à l'association de fichiers sous Windows, mais ce qui est plus puissant que l'association de fichiers est qu'elle peut non seulement juger en fonction du nom du suffixe du fichier, mais également l'ouvrir avec différents programmes basés sur sur le contenu du fichier (Magic Bytes) . Un scénario d'utilisation typique consiste à utiliser qemu pour exécuter des fichiers binaires sur d'autres plates-formes d'architecture.
Activer binfmt-misc
Pour l'activer temporairement, utilisez la commande suivante :
$ sudo mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
Cette méthode deviendra invalide après le redémarrage. Si vous souhaitez qu'elle dure longtemps, vous pouvez ajouter une ligne dans le fichier /etc/fstab :
none /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0
Vous pouvez utiliser la commande suivante pour vérifier si l'ouverture a réussi :
- $ mount | grep binfmt_misc
- binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
- $ ls -l /proc/sys/fs/binfmt_misc
- 总用量 0
- --w------- 1 root root 0 2月 5 22:55 register
- -rw-r--r-- 1 root root 0 2月 5 22:55 status
Préparez d'abord un programme avec l'architecture arm64. Après l'avoir exécuté, une erreur est signalée :
bash: ./go-test:无法执行二进制文件: 可执行文件格式错误
Maintenant, exécutons la commande apt install qemu-user-binfmt, puis exécutons le programme arm64 ci-dessus et constatons qu'il peut fonctionner normalement. Après avoir installé qemu-user-binfmt, plusieurs fichiers seront créés dans le répertoire /proc/sys/fs/binfmt_misc, dont un qemu-aarch64. Jetons un coup d'œil au contenu de ce fichier :
- root@ubuntu:/proc/sys/fs/binfmt_misc# cat qemu-aarch64
- enabled
- interpreter /usr/bin/qemu-aarch64-static
- flags: OC
- offset 0
- magic 7f454c460201010000000000000000000200b700
- mask ffffffffffffff00fffffffffffffffffeffffff
- root@ubuntu:/proc/sys/fs/binfmt_misc#
Ce fichier décrit le fichier de règles :
La première ligne activée indique que la règle est activée ;
L'interpréteur de deuxième ligne /usr/bin/qemu-aarch64-static indique d'utiliser /usr/bin/qemu-aarch64-static pour exécuter le fichier binaire ;
La troisième ligne : OC représente le drapeau en cours d'exécution, la signification spécifique est la suivante :
P : signifie préserver-argv, ce qui signifie que lors de l'appel du simulateur, les paramètres d'origine (argv) seront conservés.Ceci est utile dans les situations où les programmes silencieux doivent connaître leur propre nom (c'est-à-dire argv[0]) au moment de l'exécution.
O : représente le décalage, ce qui signifie qu'avant de démarrer le simulateur, un décalage doit être lu dans le fichier binaire, et ce décalage sera utilisé comme paramètre du simulateur.
C: signifie informations d'identification, ce qui signifie que l'émulateur s'exécutera avec le même ID utilisateur et ID de groupe utilisés par le programme d'origine, ce qui permet de garantir que l'émulateur s'exécute avec les mêmes autorisations que le programme d'origine.
La quatrième ligne : offset 0 signifie commencer à lire le fichier à partir de la valeur 0 ;
La cinquième ligne : magic 7f454c460201010000000000000000000200b700 représente l'octet modulo à faire correspondre ;
Le champ magique dans l'en-tête du fichier ELF de l'architecture arm64 est le suivant, ce qui signifie que le système de fichiers binfmt_misc peut déterminer quel simulateur d'architecture utiliser pour exécuter le fichier en fonction du champ magique du fichier ELF :
Voici deux architectures différentes
Architecture Mips : 7f454c4601020100000000000000000000020008
Architecture arm64 : 7f454c460201010000000000000000000200b700
Ligne 6 : mask ffffffffffffff00ffffffffffffffffffffff représente le masque d'octet, qui peut être utilisé pour ignorer certains octets sans importance dans le fichier.
Maintenant, nous utilisonsdockerLa commande exécute une image arm64 :
- $ docker run -it arm64v8/ubuntu bash
- Unable to find image 'arm64v8/ubuntu:latest' locally
- latest: Pulling from arm64v8/ubuntu
- 005e2837585d: Pull complete
- Digest: sha256:ba545858745d6307f0d1064d0d25365466f78d02f866cf4efb9e1326a4c196ca
- Status: Downloaded newer image for arm64v8/ubuntu:latest
- standard_init_linux.go:207: exec user process caused "no such file or directory"
Après quelques explorations, j'ai découvert que tant que j'exécutais la commande suivante :apt install qemu-user-static
, puis démarrez DockerrécipientC'est normal.
La complexité de la compilation croisée ne réside pas dans Docker, mais dans le programme lui-même. Par exemple, les programmes Go peuvent facilement être compilés de manière croisée. Il vous suffit d'exécuter les deux variables d'environnement GOOS et GOARCH lors de la construction du programme à l'aide de go build.
Pour utiliser buildx pour créer une image multiplateforme, nous devons d'abord créer un générateur, qui peut être traduit par générateur.
Utilisez la commande docker buildx ls pour afficher la liste des générateurs :
- root@ubuntu:/proc# docker buildx ls
- NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
- mybuild * docker-container
- mybuild0 unix:///var/run/docker.sock running linux/arm64*, linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386
- vigilant_hugle docker-container
- vigilant_hugle0 unix:///var/run/docker.sock stopped
- default docker
- default default running linux/amd64, linux/386
Le signe * indique le constructeur actuellement utilisé Lorsque nous exécutons la commande docker build, nous utilisons ce constructeur pour créer l'image. DRIVER/ENDPOINT dans la deuxième colonne indique le pilote utilisé. buildx prend en charge les pilotes suivants :
Étant donné que le générateur par défaut utilisant le pilote Docker ne prend pas en charge la création d'images multiplateformes à l'aide d'une seule commande (le paramètre --platform du générateur par défaut n'accepte qu'une seule valeur), nous devons créer un nouveau générateur à l'aide du pilote Docker-container. .
La syntaxe de la commande est la suivante :
$ docker buildx create --name=<builder-name> --driver=<driver> --driver-opt=<driver-options>
La signification des paramètres est la suivante :
--name : nom construit, obligatoire.
--driver : pilote Builder, la valeur par défaut est docker-container.
--driver-opt : options du pilote. Par exemple, l'option --driver-opt=image=moby/buildkit:v0.11.3 peut installer la version spécifiée de BuildKit. La valeur par défaut est moby/buildkit.
Nous pouvons créer un nouveau constructeur en utilisant la commande suivante :
- $ docker buildx create --name mybuilder
- mybuilder
Vérifiez à nouveau la liste des constructeurs :
- $ docker buildx ls
- NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
- mybuilder * docker-container
- mybuilder0 unix:///var/run/docker.sock inactive
- default docker
- default default running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
- desktop-linux docker
- desktop-linux desktop-linux running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
Vous pouvez constater que la version sélectionnée a été basculée vers Mybuilder. Si elle n'est pas sélectionnée, vous devez utiliser manuellement la commande docker buildx use mybuilder pour changer de constructeur.
Notre mybuilder nouvellement créé est actuellement inactif et doit être démarré avant de pouvoir être utilisé.
- $ docker buildx inspect --bootstrap mybuilder
- [+] Building 16.8s (1/1) FINISHED
- => [internal] booting buildkit 16.8s
- => => pulling image moby/buildkit:buildx-stable-1 16.1s
- => => creating container buildx_buildkit_mybuilder0 0.7s
- Name: mybuilder
- Driver: docker-container
-
- Nodes:
- Name: mybuilder0
- Endpoint: unix:///var/run/docker.sock
- Status: running
- Buildkit: v0.9.3
- Platforms: linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
La sous-commande inspect est utilisée pour vérifier l'état de la construction. Utilisez le paramètre --bootstrap pour démarrer le générateur mybuilder. Vérifiez à nouveau la liste des générateurs. L'état de mybuilder est devenu en cours d'exécution.
- $ docker buildx ls
- NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
- mybuilder * docker-container
- mybuilder0 unix:///var/run/docker.sock running v0.9.3 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
- default docker
- default default running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
- desktop-linux docker
- desktop-linux desktop-linux running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
La valeur affichée dans la colonne PLATEFORMES
linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6 sont pris en charge par le constructeur actuel. Tous plates-formes.
Utilisez maintenant la commande docker ps pour voir que le conteneur BuildKit correspondant au constructeur mybuilder a été démarré.
- $ docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- b8887f253d41 moby/buildkit:buildx-stable-1 "buildkitd" 4 minutes ago Up 4 minutes buildx_buildkit_mybuilder0
Ce conteneur est utilisé pour nous aider à créer des images multiplateformes. Ne le supprimez pas manuellement.
$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go .
La syntaxe de docker buildx build est la même que celle de docker build. Le paramètre --platform indique la plateforme cible pour construire l'image, -t indique le Tag de l'image, . indique que le contexte est le répertoire actuel.。
La seule chose qui ne fonctionne pas est la prise en charge du paramètre --platform. Le paramètre --platform de docker build ne prend en charge que la transmission d'informations sur une seule plate-forme, telle que --platform linux/arm64, ce qui signifie qu'une seule image de plate-forme peut être construit à la fois.
L'utilisation de docker buildx build pour créer une image prend en charge la transmission de plusieurs informations de plate-forme en même temps, séparées par des virgules anglaises, réalisant ainsi la fonction de création de plusieurs images multiplateformes avec une seule commande.
Après avoir exécuté la commande ci-dessus, nous recevrons un avertissement :
WARNING: No output specified with docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load
Cet avertissement nous rappelle que nous n'avons pas spécifié de sortie pour le pilote docker-container. Les résultats générés ne seront conservés que dans le cache de build. Utilisez --push pour pousser l'image vers le référentiel distant Docker Hub et utilisez --load. pour enregistrer l'image localement.
En effet, notre mybuilder nouvellement créé démarre un conteneur pour exécuter BuildKit. Il ne peut pas directement générer l'image multiplateforme construite sur la machine locale ou la transmettre à la machine distante. L'utilisateur doit spécifier manuellement l'emplacement de sortie.
Nous pouvons essayer de spécifier --load pour enregistrer l'image sur l'hôte local.
- $ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go . --load
- [+] Building 0.0s (0/0)
- ERROR: docker exporter does not currently support exporting manifest lists
Le résultat sera un journal des erreurs. Il semble qu'il ne prenne pas en charge l'exportation d'images multiplateformes vers le local. C'est en fait parce que plusieurs --platforms sont transmises. Si --platform ne transmet qu'une seule plate-forme, vous pouvez utiliser --load pour afficher l'image construite sur celle-ci. machine.
Ensuite, nous ne pouvons transmettre l'image multiplateforme vers l'entrepôt distant que via le paramètre --push. Cependant, avant de faire cela, vous devez vous assurer d'utiliser la connexion Docker pour terminer la connexion.
$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go . --push
Connectez-vous maintenant à Docker Hub et vous pourrez voir l'image multiplateforme poussée.
Nous pouvons également utiliser imagestools pour vérifier les informations manifestes de l'image multiplateforme. Cette commande ne peut être utilisée que pour obtenir des informations sur l'image dans l'entrepôt, et les images locales ne peuvent pas être visualisées.
- $ docker buildx imagetools inspect jianghushinian/hello-go
- Name: docker.io/jianghushinian/hello-go:latest
- MediaType: application/vnd.docker.distribution.manifest.list.v2+json
- Digest: sha256:51199dadfc55b23d6ab5cfd2d67e38edd513a707273b1b8b554985ff562104db
-
- Manifests:
- Name: docker.io/jianghushinian/hello-go:latest@sha256:8032a6f23f3bd3050852e77b6e4a4d0a705dfd710fb63bc4c3dc9d5e01c8e9a6
- MediaType: application/vnd.docker.distribution.manifest.v2+json
- Platform: linux/arm64
-
- Name: docker.io/jianghushinian/hello-go:latest@sha256:fd46fd7e93c7deef5ad8496c2cf08c266bac42ac77f1e444e83d4f79d58441ba
- MediaType: application/vnd.docker.distribution.manifest.v2+json
- Platform: linux/amd64
Comme vous pouvez le voir, cette image multiplateforme contient des images de deux plateformes cibles, à savoir linux/arm64 et linux/amd64.