2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
buildx ist ein offiziell von Docker bereitgestelltes Build-Tool, das Benutzern beim schnellen und effizienten Erstellen von Docker-Images helfen kann und die Erstellung mehrerer Plattformen unterstützt. Mit buildx können Benutzer Images für mehrere Architekturen, wie z. B. x86- und Arm-Architekturen, in einem einzigen Befehl erstellen, ohne mehrere Build-Befehle manuell ausführen zu müssen. Darüber hinaus unterstützt buildx auch die mehrstufige Erstellung und Zwischenspeicherung von Dockerfiles, wodurch die Effizienz und Geschwindigkeit der Image-Erstellung erheblich verbessert werden kann.
buildx ist ein CLI-Plug-in, das Docker-Builds verwaltet. Die zugrunde liegende Ebene verwendet BuildKit, um die Docker-Build-Funktionen zu erweitern.
BuildKit ist eine leistungsstarke Build-Engine, die offiziell von Docker bereitgestellt wird und als Ersatz für die ursprüngliche Build-Engine von Docker verwendet werden kann. Im Vergleich zur Original-Engine bietet BuildKit eine schnellere Build-Geschwindigkeit, höhere Parallelität, weniger Ressourcenverbrauch und bessere Sicherheit.
Um buildx zu installieren und zu verwenden, muss die Versionsnummer der Docker Engine größer oder gleich 19.03 sein.
Der Builder unterstützt verschiedene Strategien zum Erstellen plattformübergreifender Images.
Wenn Sie Docker Desktop verwenden, wird QEMU bereits unterstützt und ist die einfachste Strategie zum Erstellen plattformübergreifender Images. Es sind keine Änderungen an der ursprünglichen Docker-Datei erforderlich. BuildKit implementiert die plattformübergreifende Programmausführung über die Linux-Kernel-Funktion binfmt_misc.
Arbeitsprinzip:
QEMU ist ein Prozessorsimulator, der verschiedene CPU-Architekturen simulieren kann. Wir können ihn als eine andere Form einer virtuellen Maschine verstehen. In buildx wird QEMU verwendet, um während des Build-Prozesses Binärdateien für nicht-native Architekturen auszuführen. Wenn Sie beispielsweise ein ARM-Image auf einem x86-Host erstellen, kann QEMU die ARM-Umgebung simulieren und ARM-Binärdateien ausführen.
binfmt_misc ist ein Modul des Linux-Kernels, das es Benutzern ermöglicht, ausführbare Dateiformate und entsprechende Interpreter zu registrieren.Wenn der Kernel auf eine ausführbare Datei unbekannten Formats stößt, wird binfmt_misc verwendet, um den mit dem Dateiformat verknüpften Interpreter (in diesem Fall QEMU) zu finden und die Datei auszuführen . Diese Funktion ist auf der rk3568-Plattform deaktiviert.
Die Kombination von QEMU und binfmt_misc ermöglicht plattformübergreifendes Erstellen über buildx. Dadurch können wir Docker-Images für eine Architektur auf einem Host für andere Architekturen erstellen, ohne die eigentliche Zielhardware besitzen zu müssen.
Obwohl Docker Desktop mit binfmt_misc-Unterstützung für andere Plattformen vorkonfiguriert ist, müssen Sie für andere Versionen von Docker möglicherweise das tonistiigi/binfmt-Image verwenden, um einen privilegierten Container für die Unterstützung zu starten.
docker run --privileged --rm tonistiigi/binfmt --install all
Durch Ausführen dieses Befehls werden Interpreterprogramme verschiedener Architekturen installiert, d. h. der Qemu-Simulator im Verzeichnis /usr/bin:
Das Modul binfmt_misc wird auf unseren Kompilierungsserver geladen:
Docker Buildx ist eine experimentelle Funktion von Docker, die die Build-Funktionen von Docker erweitert, einschließlich der Verwendung von Multi-Node, Qemu usw. QEMU ist eine Open-Source-Software für virtuelle Maschinen, die verschiedene CPUs und andere Hardware simulieren kann, sodass wir ein Image eines anderen Betriebssystems auf einem Betriebssystem erstellen können.
Die Verwendung der qemu-Funktion von Docker Buildx kann uns dabei helfen, Docker-Images für mehrere verschiedene Architekturen (wie ARM, MIPS usw.) zu erstellen.
Das Folgende ist ein einfaches Beispiel, das zeigt, wie Sie mit Docker Buildx und QEMU ein Docker-Image für die ARM-Architektur erstellen:
- # 创建一个新的 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 .
In diesem Beispiel,--platform
Der Parameter gibt an, dass die Zielplattform, für die wir bauen möchten, ARM v7 ist. Auf diese Weise wird Docker QEMU verwenden, um eine ARM-Umgebung zu simulieren und ein Docker-Image für die ARM-Architektur auf der Maschine mit x86-Architektur zu erstellen.
binfmt-misc ist eine vom Linux-Kernel bereitgestellte Funktion, die der Dateizuordnung unter Windows ähnelt. Sie ist jedoch leistungsfähiger als die Dateizuordnung, da sie nicht nur anhand des Dateisuffixnamens beurteilen kann, sondern auch anhand der Datei mit verschiedenen Programmen geöffnet werden kann Inhalt (Magic Bytes) . Ein typisches Verwendungsszenario besteht darin, qemu zum Ausführen von Binärdateien auf anderen Architekturplattformen zu verwenden.
Aktivieren Sie binfmt-misc
Um es vorübergehend zu aktivieren, verwenden Sie den folgenden Befehl:
$ sudo mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
Diese Methode wird nach dem Neustart ungültig. Wenn Sie möchten, dass sie längere Zeit wirksam wird, können Sie der Datei /etc/fstab eine Zeile hinzufügen:
none /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0
Mit dem folgenden Befehl können Sie überprüfen, ob das Öffnen erfolgreich war:
- $ 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
Bereiten Sie zunächst ein Programm mit arm64-Architektur vor. Nach der Ausführung wird ein Fehler gemeldet:
bash: ./go-test:无法执行二进制文件: 可执行文件格式错误
Führen wir nun den Befehl apt install qemu-user-binfmt aus, führen Sie dann das obige arm64-Programm aus und stellen Sie fest, dass es normal ausgeführt werden kann. Nach der Installation von qemu-user-binfmt werden mehrere Dateien im Verzeichnis /proc/sys/fs/binfmt_misc erstellt, darunter eine qemu-aarch64. Schauen wir uns den Inhalt dieser Datei an:
- 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#
Diese Datei beschreibt die Regeldatei:
Die erste aktivierte Zeile zeigt an, dass die Regel aktiviert ist.
Der zweite Zeileninterpreter /usr/bin/qemu-aarch64-static gibt an, /usr/bin/qemu-aarch64-static zum Ausführen der Binärdatei zu verwenden;
Die dritte Zeile: OC stellt das laufende Flag dar, die spezifische Bedeutung ist wie folgt:
P: steht für „preserve-argv“, was bedeutet, dass beim Aufruf des Simulators die ursprünglichen Parameter (argv) erhalten bleiben.Dies ist nützlich für Situationen, in denen stille Programme zur Laufzeit ihren eigenen Namen (z. B. argv[0]) kennen müssen
O: stellt den Offset dar, was bedeutet, dass vor dem Starten des Simulators ein Offset aus der Binärdatei gelesen werden muss und dieser Offset als Parameter des Simulators verwendet wird.
C: steht für Anmeldeinformationen, was bedeutet, dass der Emulator mit derselben Benutzer-ID und Gruppen-ID ausgeführt wird, die auch das Originalprogramm verwendet, wodurch sichergestellt wird, dass der Emulator mit denselben Berechtigungen wie das Originalprogramm ausgeführt wird.
Die vierte Zeile: Offset 0 bedeutet, dass mit dem Lesen der Datei ab dem Wert 0 begonnen wird.
Die fünfte Zeile: magic 7f454c460201010000000000000000000200b700 stellt das abzugleichende Modulo-Byte dar;
Das magische Feld im Header der ELF-Datei der arm64-Architektur lautet wie folgt, was bedeutet, dass das Dateisystem binfmt_misc basierend auf dem magischen Feld in der ELF-Datei bestimmen kann, welcher Architektursimulator zum Ausführen der Datei verwendet werden soll:
Nachfolgend sind zwei verschiedene Architekturen aufgeführt
Mips-Architektur: 7f454c4601020100000000000000000000020008
arm64-Architektur: 7f454c460201010000000000000000000200b700
Zeile 6: mask ffffffffffffff00ffffffffffffffffffffff stellt die Bytemaske dar, mit der einige unwichtige Bytes in der Datei ignoriert werden können.
Jetzt verwenden wirDockerDer Befehl führt ein arm64-Image aus:
- $ 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"
Nach einiger Erkundung habe ich herausgefunden, dass solange ich den folgenden Befehl ausführe:apt install qemu-user-static
, dann Docker startenContainerEs ist normal.
Die Komplexität der Cross-Compilation liegt nicht in Docker, sondern im Programm selbst. Beispielsweise können Go-Programme problemlos übergreifend kompiliert werden. Sie müssen lediglich die beiden Umgebungsvariablen GOOS und GOARCH ausführen, wenn Sie das Programm mit go build erstellen.
Um mit buildx ein plattformübergreifendes Image zu erstellen, müssen wir zunächst einen Builder erstellen, der als Builder übersetzt werden kann.
Verwenden Sie den Befehl docker buildx ls, um die Builder-Liste anzuzeigen:
- 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
Das *-Zeichen gibt den aktuell verwendeten Builder an. Wenn wir den Docker-Build-Befehl ausführen, verwenden wir diesen Builder, um das Image zu erstellen. DRIVER/ENDPOINT in der zweiten Spalte gibt den verwendeten Treiber an. buildx unterstützt die folgenden Treiber:
Da der Standard-Builder, der den Docker-Treiber verwendet, das Erstellen plattformübergreifender Images mit einem einzigen Befehl nicht unterstützt (der Parameter „--platform“ des Standard-Builders akzeptiert nur einen einzelnen Wert), müssen wir einen neuen Builder mit dem Docker-Container-Treiber erstellen .
Die Befehlssyntax lautet wie folgt:
$ docker buildx create --name=<builder-name> --driver=<driver> --driver-opt=<driver-options>
Die Bedeutung der Parameter ist wie folgt;
--name: Zu erstellender Name, erforderlich.
--driver: Builder-Treiber, Standard ist Docker-Container.
--driver-opt: Treiberoptionen. Mit der Option --driver-opt=image=moby/buildkit:v0.11.3 kann die angegebene Version von BuildKit installiert werden.
Mit dem folgenden Befehl können wir einen neuen Builder erstellen:
- $ docker buildx create --name mybuilder
- mybuilder
Überprüfen Sie die Builder-Liste noch einmal:
- $ 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
Sie können feststellen, dass der ausgewählte Build auf Mybuilder umgestellt wurde. Wenn er nicht ausgewählt ist, müssen Sie den Docker-Buildx-Befehl mybuilder manuell verwenden, um den Builder zu wechseln.
Unser neu erstellter mybuilder ist derzeit inaktiv und muss gestartet werden, bevor er verwendet werden kann.
- $ 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
Der Unterbefehl inspect wird verwendet, um den Build-Status zu überprüfen. Verwenden Sie den Parameter --bootstrap, um den Builder-Status erneut zu starten.
- $ 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
Der in der Spalte PLATTFORMEN angezeigte Wert
linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6 werden vom aktuellen Builder unterstützt. Alle Plattformen.
Verwenden Sie nun den Befehl docker ps, um festzustellen, ob der BuildKit-Container, der dem Builder mybuilder entspricht, gestartet wurde.
- $ 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
Dieser Container wird verwendet, um uns beim Erstellen plattformübergreifender Images zu unterstützen. Löschen Sie ihn nicht manuell.
$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go .
Die Syntax von Docker Buildx Build ist dieselbe wie die von Docker Build. Der Parameter --platform gibt die Zielplattform für die Erstellung des Images an, -t gibt das Tag des Images an. . gibt an, dass der Kontext das aktuelle Verzeichnis ist。
Das Einzige, was nicht funktioniert, ist die Unterstützung des Parameters --platform von Docker Build. Er unterstützt nur die Übergabe einer Plattforminformation, z. B. --platform linux/arm64, was bedeutet, dass ein einzelnes Plattform-Image dies kann auf einmal gebaut werden.
Die Verwendung von Docker Buildx Build zum Erstellen eines Images unterstützt die gleichzeitige Übertragung mehrerer Plattforminformationen, getrennt durch englische Kommas, wodurch die Funktion des Erstellens mehrerer plattformübergreifender Images mit nur einem Befehl realisiert wird.
Nachdem wir den obigen Befehl ausgeführt haben, erhalten wir eine Warnung:
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
Diese Warnung erinnert uns daran, dass wir keine Ausgabe für den Docker-Container-Treiber angegeben haben. Die generierten Ergebnisse werden nur im Build-Cache gespeichert und verwenden --load um das Bild lokal zu speichern.
Dies liegt daran, dass unser neu erstellter Mybuilder einen Container zum Ausführen von BuildKit startet. Er kann das erstellte plattformübergreifende Image nicht direkt auf den lokalen Computer ausgeben oder auf den Remote-Computer übertragen. Der Benutzer muss den Ausgabeort manuell angeben.
Wir können versuchen, --load anzugeben, um das Bild auf dem lokalen Host zu speichern.
- $ 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
Das Ergebnis ist ein Fehlerprotokoll. Es scheint, dass der Export von plattformübergreifenden Bildern auf die lokale Plattform nicht unterstützt wird. Dies liegt tatsächlich daran, dass mehrere --platforms nur eine Plattform übergeben Maschine.
Dann können wir das plattformübergreifende Image nur über den Parameter --push in das Remote-Warehouse übertragen. Bevor Sie dies tun, müssen Sie jedoch sicherstellen, dass Sie die Docker-Anmeldung verwenden, um die Anmeldung abzuschließen.
$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go . --push
Melden Sie sich nun bei Docker Hub an und Sie können das gepushte plattformübergreifende Image sehen.
Wir können auch Imagestools verwenden, um die Manifestinformationen des plattformübergreifenden Images zu überprüfen. Dieser Befehl kann nur zum Abrufen von Image-Informationen im Warehouse verwendet werden, lokale Images können nicht angezeigt werden.
- $ 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
Wie Sie sehen können, enthält dieses plattformübergreifende Image Bilder von zwei Zielplattformen, nämlich Linux/Arm64 und Linux/AMD64.