Neuigkeiten von trion.
Immer gut informiert.

DockerHub Multi-Arch Image als Autobuild

Bereits in diesem Beitrag zu Docker Multi-Arch Images wurden die Grundlagen erläutert, wie Docker-Images dank Manifest automatisch passend für die jeweilige Plattform ausgewählt werden.

Doch die Erstellung solcher multiplen Images und der zugehörigen Manifest-Dateien ist mit dem automatischen Build auf Docker Hub nicht so intuitiv umsetzbar, wie bei regulären Images. Eine Lösung kann da ein eigener Buildserver inkl. Build-Agents für die zu unterstützenden Plattformen darstellen.

Dieser Beitrag erklärt, wie unter Verwendung von QEMU zur Cross-Compilation und den DockerHub Build Hooks entsprechende Docker-Images und das Manifest vollautomatisch erzeugt und publiziert werden können. (Hintergründe zum Cross Build von Docker Images finden sich hier: Docker Multi-Arch Images )

Update: In diesem Artikel wird ein ähnliches Verfahren, jedoch mit GitHub Actions vorgestellt: Multi Arch Images mit GitHub Actions.

Zur Veranschaulichung dient das Docker-Image für Angular CLI, dass auf DockerHub zu finden ist: link:https://hub.docker.com/r/trion/ng-cli

Um das Docker-Image für mehrere Plattformen bereitzustellen müssen folgende Vorraussetzungen erfüllt werden:

  • Build für die jeweilige Plattform

  • Bereitstellung des Multi-Arch Manifests

Zunächst werden mehrere Builds durch entsprechende Dockerfiles definiert.

  • Dockerfile das bisher bereits für AMD64 genutzte Dockerfile

  • Dockerfile.arm32v7 für 32bit ARM Plattform

  • Dockerfile.arm64v8 für 64bit ARM Plattform

An dem Dockerfile für die AMD64 Linux Plattform ändert sich zunächst einmal nichts. Zur Veranschaulichung ist die erste Zeile des Dockerfile im folgenden Quellcode zu sehen.

Erste Zeile des Dockerfile für die AMD64 Linux Plattform
FROM node:lts-slim
...

Da DockerHub lediglich AMD64 Builder bereitstellt, ist die einfachste Möglichkeit um andere Plattformen bereitzustellen der Einsatz von QEMU. Dazu muss QEMU zur Ausführung mit binfmt registriert werden, was dank der Build-Hooks von DockerHub möglich ist. Ein entsprechender Hook, der vor allen Builds ausgeführt wird, ist unter hooks/pre_build zu definieren.

Pre-Build Hook für den DockerHub Builder
#!/bin/bash
docker run --rm --privileged multiarch/qemu-user-static:register --reset

Binaries für andere Plattformen werden anschließend durch QEMU ausgeführt. Dazu muss QEMU jedoch auch als Binary im jeweiligen Build-Container zur Verfügung stehen. Um das zu erreichen, wird ein Docker Multi-Stage-Build verwendet, der als erstes QEMU herunterlädt, wie es das folgende Dockerfile für die ARM 64bit Architektur umsetzt.

Außerdem muss explizit ein Docker Base-Image für die Zielplattform ausgewählt werden - da Docker Hub stets mit AMD64 baut, würde sonst das AMD64 Base Image verwendet, was ja gerade nicht das Ziel ist.

Verkürztes Dockerfile für ARM 64bit Linux mit QEMU
FROM alpine AS qemu

#QEMU Download
ENV QEMU_URL https://github.com/balena-io/qemu/releases/download/v3.0.0%2Bresin/qemu-3.0.0+resin-aarch64.tar.gz
RUN apk add curl && curl -L ${QEMU_URL} | tar zxvf - -C . --strip-components 1

FROM arm64v8/node:lts-slim
# Add QEMU
COPY --from=qemu qemu-aarch64-static /usr/bin

Hinweis: Bei 32bit ARM ist statt qemu-aarch64-static analog das qemu-arm-static zu verwenden.
Bei diesem Verfahren sind durch die Emulation der Plattform längere Buildzeiten als Trade-Off in Kauf zu nehmen.

Als nächstes Element müssen die Builds für die jeweiligen Zielplattformen auch getriggert werden. Dazu werden bei DockerHub die verschiedenen Dockerfiles und zugehörigen Image-Tags konfiguriert, wie in der folgenden Abbildung gezeigt.

Abbildung 1. Docker Hub Multi Arch Build Konfiguration

Als finales Element fehlt nun nur noch das Manifest, in dem spezifiziert ist, welche Image-Tags zur jeweiligen Plattform gehören.

Manifest für Angular CLI Multi-Arch Image
image: trion/ng-cli:latest
manifests:
  - image: trion/ng-cli:latest-amd64
    platform:
      architecture: amd64
      os: linux
  - image: trion/ng-cli:latest-arm64v8
    platform:
      architecture: arm64
      os: linux
      variant: v8
  - image: trion/ng-cli:latest-arm32v7
    platform:
      architecture: arm
      os: linux
      variant: v7

Damit das Manifest auch passend zum Docker-Image-Tag automatisch angelegt wird, kann wieder ein DockerHub Build-Hook verwendet werden. Auch hier ist die Implementierung relativ simpel, da lediglich das Manifest bereitgestellt werden muss. Dazu wird das Binary manifest-tool verwendet, da auf DockerHub derzeit der Manifest Support nicht aktiviert ist. (Der Manifest Support ist noch als experimentell eingestuft, und Docker Hub hat keine experimentellen Features in ihren Buildern aktiviert.)

Der Hook soll ausgeführt werden, wenn ein Image gebaut und auf DockerHub gepusht wurde, daher wird als Datei hooks/post_push verwendet.

Build Hook zur Bereitstellung des Multi-Arch Manifestes
#!/bin/bash
curl -Lo manifest-tool https://github.com/estesp/manifest-tool/releases/download/v0.9.0/manifest-tool-linux-amd64
chmod +x manifest-tool

./manifest-tool push from-spec multi-arch-manifest.yaml

Mit dieser Konfiguration kann nun automatisiert für die Plattformen Linux AMD64, ARM 32bit und ARM 64bit ein Image gebaut und auf DockerHub als Multi-Arch Image bereitgestellt werden.




Zu den Themen Kubernetes, Docker und Cloud Architektur bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:

Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.

Feedback oder Fragen zu einem Artikel - per Twitter @triondevelop oder E-Mail freuen wir uns auf eine Kontaktaufnahme!

Zur Desktop Version des Artikels