Docker-Registry auf ARM 64 - Cross-Compiling Docker-Images
Bisher gibt es die offizielle Docker Registry lediglich als x86 Docker Image. Damit ist ein Betrieb unter ARM oder ARM 64 aktuell nicht möglich. Obwohl Docker Multi-Arch-Support eingeführt hat, also die Möglichkeit unter dem selben Image-Namen verschiedene Architekturen zu bedienen, ist das bei dem hauseigenen Image leider noch nicht umgesetzt worden. In diesem Beitrag geht es nun darum, ein passendes Image durch Cross-Compilation zu erstellen und damit eine Registry bereit zu stellen.
Der Betrieb des mit Docker erstellen Image wird unter CRI-O erfolgen, womit die Interoperabilität, dank der Standardisierung von OCI, unter Beweis gestellt wird.
Cross-Build Setup
Um auf Intel- / AMD-64-Architekturen ARM-Images auszuführen, behilft man sich einiger Tricks: Zum Einen wird QEMU verwendet, um eine andere Architektur zu simulieren. Damit lässt sich nicht nur ARM emulieren, auch Exoten wie ein s390 IBM-Host sind möglich. Zum Anderen wird das im Linux-Kernel vorhandene binfmt Feature genutzt, um sicherzustellen, dass QEMU zur Ausführung von Programmen verwendet wird, wenn die aktuelle Plattform eine andere ist, als die Zielplattform des Programms.
Damit lassen sich - ein geeignetes Base-Image vorausgesetzt - auf jeder Plattform Docker-Images für beliebige Zielplattformen bauen.
(Ein paar Voraussetzungen, wie z.B. ein statisch gelinktes QEMU im Image werden an dieser Stelle nicht weiter betrachtet.)
Aus dem Docker-Repository multiarch
können praktischerweise entsprechende Base-Images bezogen werden.
Zusätzlich wird auch ein Image bereitgestellt, mit dem die notwendige Einrichtung des binfmt Supports einfach umzusetzen ist: multiarch/qemu-user-static:register
$ docker run --rm --privileged multiarch/qemu-user-static:register --reset
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-armeb-static as binfmt interpreter for armeb
...
Ist dieser Schritt erledigt, kann testweise ein ARM-64-Image verwendet werden, um darin eine Shell auszuführen.
$ docker run -it --rm multiarch/alpine:aarch64-latest-stable /bin/sh
/ \# uname -a
Linux 35f7362a7642 4.15.0-32-generic \#35-Ubuntu SMP Fri Aug 10 17:58:07 UTC 2018 aarch64 Linux
/ \#
Als nächstes kann das Docker-Image für die Docker-Registry gebaut werden.
Cross-Build Docker-Registry für ARM
Da es bereits einen Pull-Request gibt, um Multi-Arch-Support für das offizielle Registry-Image einzuführen, kann das zugrundeliegende git-Projekt als Basis verwendet werden. Das Projekt wird also lokal geclont und der passende Branch ausgecheckt.
$ git clone https://github.com/tianon/docker-registry-image.git
$ cd docker-registry-image/
$ git checkout multiarch
Theoretisch kann nun mittels docker build -t registry .
das Image gebaut werden.
Doch hier zeigt sich, dass eine Emulation nicht immer perfekt funktioniert:
Abgesehen von der niedrigeren Ausführungsgeschwindigkeit von QEMU verhält sich das System auch etwas anders.
Das fällt nun auch auf, während der Go-Compiler die Sourcen der Docker-Registry übersetzt.
Bei älteren Go-Versionen wurde das Verhalten toleriert, neuere Go-Versionen brechen jedoch die Compilierung mit einem Fehler ab.
(Siehe Ticket https://github.com/golang/go/issues/24656 )
Zum Glück kann die Docker-Registry auch mit einem älteren Go-Compiler übersetzt werden.
Dazu wird die FROM
Zeile im Dockerfile der Docker Registry auf eine ältere Version von Alpine konfiguriert, die dann auch ältere Go-Werkzeuge mitbringt:
FROM multiarch/alpine:aarch64-v3.7
Nun kann das Docker-Image ganz normal gebaut werden.
$ docker build -t registry:2 .
...
Anschließend lässt sich das Image durch docker save
exportieren und auf ein Zielsystem kopieren.
Dort kann das Image mit docker load
importiert werden.
$ docker save registry:2 -o registry.arm64.img
$ scp registry.arm64.img 10.23.15.1:~/
...
$ docker load registry.arm64.img
Verwendung mit CRI-O und runc
Das mit Docker gebaute Image der Docker-Registry soll nun mit CRI-O bzw. runc als Container-Umgebung in einem Kubernetes-Cluster betrieben werden. Anders als Docker, kann CRI-O zwar Images pushen und pullen, jedoch nicht importieren oder exportieren.
Dafür gibt es z.B. das Werkzeug skopeo
, das mit OCI und Docker-v2-Images arbeiten kann.
Damit lässt sich das mit Docker exportierte Image durch das copy
Kommando importieren.
$ skopeo copy docker-archive:registry.arm64.img \ containers-storage:docker.io/library/registry:2
INFO[0000] [graphdriver] using prior storage driver: overlay
Getting image source signatures
Copying blob sha256:e2f253d59b1422b0bb333773aa217ffdd89e9cfc0214caf8a08e48b27eddc4d9
10.30 MB / 10.30 MB [======================================================] 1s
Copying blob sha256:c2df8775fe81d7e3acb7a33c0940f5b8334163a21d2000ed43de7605207b45fe
3.69 MB / 3.69 MB [========================================================] 0s
Copying blob sha256:523414ad9b9696ae9922afa266c35648ff656ab73d9d8599da8a8c0cbd11dd59
1.52 MB / 1.52 MB [========================================================] 0s
Copying blob sha256:2763f2733114afebfc8ad24677ecf953ec03dde6d233cbe72cbcfd0a702d0e47
25.46 MB / 25.46 MB [======================================================] 3s
Copying blob sha256:41dfcef05d2375ce2a0a3f1641afd16ec8f941fcc1cb2a9327a4e65dd03cb33d
2.00 KB / 2.00 KB [========================================================] 0s
Copying config sha256:fd4ea11aea75810d7111538c91b04fe4ff96df7c17cf0c64c2d644cad0459e55
4.14 KB / 4.14 KB [========================================================] 0s
Writing manifest to image destination
Storing signatures
Anschließend zeigt crictl
das importiere Image an, und es steht bereit, um daraus Container-Instanzen zu erzeugen.
crictl
und CRI-O[root@c2-master0 ~]# crictl images
IMAGE TAG IMAGE ID SIZE
docker.io/library/registry 2 fd4ea11aea758 43MB
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.