So funktioniert eine Container-Registry: Images direkt pushen und pullen
(labs.iximiuz.com)- Container-Registries wirken auf den ersten Blick einfach, aber um Probleme wie falsche Tags, Plattform-Inkompatibilitäten, fehlende Layer oder fehlgeschlagene tatsächliche Löschungen zu debuggen, muss man ihre interne Funktionsweise unbedingt verstehen
- Der Kern einer Registry ist ein content-addressable Blob-Store, in dem alle Layer, Konfigurationsdateien und Artefakte unter ihrer Digest-Adresse gespeichert werden
- Ein Image-Push läuft in der Reihenfolge Blob-Upload, dann Bündelung per Manifest ab, während Pull den umgekehrten Ablauf nutzt: erst das Manifest abrufen, dann die Blobs nacheinander herunterladen
- Image-Löschung bedeutet nicht automatisch vollständiges Entfernen: Nur ein Untagging reicht nicht aus, man muss erst prüfen, welche Layer von anderen Manifesten gemeinsam genutzt werden, und dann die Blobs direkt löschen
- Multi-Plattform-Images werden umgesetzt, indem bei unveränderten bestehenden API-Endpunkten nur eine zusätzliche indirekte Schicht in Form eines image index (manifest list) eingeführt wird
Überblick über die Registry-API
- Die meisten modernen Container-Registries implementieren die OCI Distribution Specification, die ein API-Protokoll zur Standardisierung der Verteilung von Inhalten definiert
- Die Registry-API ist tatsächlich kompakt und leicht verständlich; sie lässt sich sogar allein mit
curldirekt bedienen
Blob-Upload und -Download
- Eine Registry ist im Wesentlichen ein content-addressable Blob-Store: Dateien werden lokal gehasht und dann mit ihrem Digest als Adresse hochgeladen
- Die einfachste Upload-Methode ist Monolithic PUT mit einer zweistufigen Struktur: zuerst die Sitzung per
POSTinitialisieren, dann den Blob perPUTsenden- Für große Dateien ist die Chunk-Upload-Methode per
POST + PATCH + PUTeffizienter, für kleine Blobs reicht Monolithic PUT jedoch aus
- Für große Dateien ist die Chunk-Upload-Methode per
- Bei erfolgreichem Upload wird eine Antwort
HTTP/2 201 Createdzusammen mit einemLocation-Header zurückgegeben, der auf den neuen Blob verweist - Für den Download reicht die Kenntnis des Digests; mit
GET /v2/<repo>/blobs/<digest>kann er direkt ausgeführt werden
Image-Push
- Ablauf eines Image-Pushs: (1) Upload jedes rootfs-Layer-Blobs → (2) Upload des image configuration-Blobs → (3) Push der Manifest-Datei, die alle Digests in einem JSON-Dokument zusammenfasst
- Das Manifest wird über den Endpunkt
PUT /v2/<repo>/manifests/<tag>hochgeladen; in diesem Moment wird auch das Tag erzeugt - Echte Clients wie
docker pushladen Blobs parallel hoch, zum Verständnis des Prinzips ist aber auch eine sequenzielle Verarbeitung möglich - Beispiel für die Struktur eines Image-Verzeichnisses:
config.json,layer-1.tar.gz,layer-2.tar.gz,manifest.json
Tag-Liste abrufen
- Über den Endpunkt
GET /v2/<repo>/tags/listlässt sich die vollständige Tag-Liste eines bestimmten Repositorys abrufen - Diese Funktion wird in der
docker-CLI nicht offengelegt und ist nur über Tools wiecurl,craneoderregctlzugänglichcraneundregctlkapseln denselben Endpunkt über den Befehlls
Image-Pull
- Der Pull-Ablauf ist die Umkehrung von Push: (1) Manifest abrufen per
GET /v2/<repo>/manifests/<tag>→ (2) alle Blobs herunterladen anhand der im Manifest angegebenen Digests - Moderne Manifeste dienen neben rootfs-Layern und Image-Konfiguration auch als universeller Speicher, der beliebige Artefakte als Blobs referenziert, darunter Helm-Charts, SBOMs, Provenance Attestations und LLM-Gewichte
Image-Löschung
- Das Löschen eines Images ist nicht trivial; das Entfernen eines Tags (Untagging) löscht das Manifest selbst nicht
- Vollständiger Löschablauf:
- (1) Tag entfernen mit
DELETE /v2/<repo>/manifests/<tag> - (2) Manifest per Digest abrufen und alle referenzierten Blobs prüfen
- (3) nur Blobs löschen, die nicht von anderen Manifesten gemeinsam genutzt werden
- (4) Manifest-Blob löschen mit
DELETE /v2/<repo>/blobs/<manifest-digest>
- (1) Tag entfernen mit
- Da eine Registry ein content-addressable Speichersystem ist, können mehrere Images denselben rootfs-Layer gemeinsam nutzen; beim Löschen wirkt sich das auf alle Images aus, die auf diesen Layer verweisen
- Alternativ kann man alle Tags entfernen und sich dann auf die Garbage-Collection-Einstellung der Registry verlassen, allerdings ist diese in öffentlichen Registries nicht immer aktiviert
Multi-Plattform-Images
- Multi-Plattform-Images werden ohne Änderungen an der Struktur der Registry-API umgesetzt — die bestehende API wird unverändert weiterverwendet, ohne neue oder angepasste Endpunkte
- Vorgehensweise:
- Jede einzelne Plattformvariante (amd64, arm64 usw.) wird zunächst zusammen mit einem eigenen Manifest digest-basiert gepusht
- Anschließend wird ein übergeordnetes Manifest namens image index (manifest list) zusammen mit dem Tag gepusht
- Bei
GET /v2/<repo>/manifests/<tag>wird entweder ein Single-Plattform-Manifest oder ein image index zurückgegeben; der Aufrufer muss beides über den Content-Type des zurückgegebenen Dokuments unterscheiden - Im Ergebnis ergänzt die Multi-Plattform-Unterstützung die bestehende Struktur nur um eine indirekte Schicht und einen zusätzlichen Schritt zum Hoch- und Herunterladen des Index-Dokuments
Schutz der Registry-API
- Die OCI Distribution Spec definiert das Authentifizierungsverfahren nicht strikt, die meisten realen Registries verwenden jedoch HTTP Basic Authentication
- Um zu verhindern, dass Zugangsdaten im Klartext übertragen werden, muss der Betrieb zwingend über HTTPS erfolgen
Noch keine Kommentare.