Deine Container-Registry kann mehr als Images

02.08.2026

Thema: alle Beiträge zu Docker

Eine Registry kennt keine Images, sie kennt Manifeste und Blobs. Was OCI-Artefakte sind, warum Helm und Trivy sie nutzen und was das mit Lock-in zu tun hat.

Inhaltsverzeichnis

Ich habe ein PDF in eine Container-Registry gepusht. Sie hat es klaglos genommen, ohne Dockerfile, ohne Umweg, ohne zu murren.

Das ist kein Trick, sondern die Antwort auf eine Frage, die kaum jemand stellt: Eine Registry kennt keine Images. Sie kennt Manifeste, Deskriptoren und Blobs. Ein Container-Image ist nur der bekannteste Sonderfall davon, und seit die OCI-Spezifikationen 1.1 im Jahr 2024 beliebige Dateitypen offiziell gemacht haben, laufen längst Helm-Charts, Schwachstellen-Datenbanken, Signaturen und KI-Modelle über dieselbe Infrastruktur.

Wer das einmal gesehen hat, betreibt seine Registry anders. Also bauen wir es nach.

Das Experiment

Alles läuft über Container, du musst nichts installieren. Zuerst eine Registry auf dem eigenen Rechner:

docker run -d --rm --name reg -p 5000:5000 registry:2

Dann irgendeine Datei, die mit Containern nichts zu tun hat. Ich nehme ein PDF, konkret einen meiner Spickzettel. Hochgeladen wird es mit ORAS, dem Standardwerkzeug für OCI-Artefakte, ebenfalls als Container:

docker run --rm --network host -v "$PWD:/work" -w /work \
  ghcr.io/oras-project/oras:v1.3.0 \
  push --plain-http localhost:5000/spickzettel:1.0 \
  --artifact-type application/vnd.trutz.spickzettel \
  spickzettel.pdf:application/pdf

Zwei Angaben sind dabei interessant. Der --artifact-type ist ein frei wählbarer Medientyp, mit dem du sagst, was das Ding ist. Und das :application/pdf hinter dem Dateinamen legt den Medientyp des Inhalts fest.

Das war es. Ein PDF liegt in einer Container-Registry.

Was im Manifest steht

Jetzt der interessante Teil. Fragen wir die Registry, was sie da eigentlich gespeichert hat:

curl -s -H "Accept: application/vnd.oci.image.manifest.v1+json" \
  http://localhost:5000/v2/spickzettel/manifests/1.0 | jq .
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "artifactType": "application/vnd.trutz.spickzettel",
  "config": {
    "mediaType": "application/vnd.oci.empty.v1+json",
    "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
    "size": 2,
    "data": "e30="
  },
  "layers": [
    {
      "mediaType": "application/pdf",
      "digest": "sha256:6fe698077a6bbeb0ca75f0ef74e40e2ea217cc2ed208fe7040a9dafcf957a3e5",
      "size": 35956,
      "annotations": {
        "org.opencontainers.image.title": "spickzettel.pdf"
      }
    }
  ]
}

Drei Stellen erklären das gesamte Konzept.

Das PDF liegt als Layer. Nicht in einem Sonderfeld, nicht in einem Anhang, sondern genau dort, wo bei einem Image die Dateisystem-Schichten stehen. Der mediaType sagt application/pdf statt application/vnd.oci.image.layer.v1.tar+gzip, und das ist der ganze Unterschied. Ein Layer ist ein Blob mit einem Digest, einer Größe und einem Typ. Was drinsteht, ist der Registry gleichgültig.

Der Config-Deskriptor ist leer. Bei einem Image steht hier die Konfiguration: Entrypoint, Umgebungsvariablen, Architektur. Ein PDF hat davon nichts. Der Wert e30= ist base64 für {}, also zwei Byte leeres JSON, und der Medientyp application/vnd.oci.empty.v1+json wurde in Spec 1.1 genau dafür eingeführt. Vorher musste man sich mit Dummy-Konfigurationen behelfen.

Die Bedeutung trägt artifactType. Das ist das Feld, an dem Werkzeuge erkennen, womit sie es zu tun haben. Ich habe mir application/vnd.trutz.spickzettel ausgedacht, und die Registry hat es widerspruchslos akzeptiert, weil sie es nicht interpretieren muss. Sie speichert es.

Damit ist die Ausgangsbehauptung belegt. Die Registry hat keine Vorstellung davon, was ein Image ist. Sie verwaltet inhaltsadressierte Blobs und JSON-Dokumente, die auf sie zeigen.

Warum das kein Bastelspaß ist

An dieser Stelle könnte man das für eine Kuriosität halten. Ist es nicht. Es ist die Grundlage dafür, wie moderne Plattform-Werkzeuge ihre Sachen ausliefern, und die Chancen stehen gut, dass du es diese Woche schon benutzt hast:

Der praktische Punkt daran: Ihr betreibt bereits eine Registry. Sie hat Authentifizierung, Zugriffsrechte, Replikation, Aufbewahrungsregeln, Prüfsummen und in aller Regel ein Backup. Für all das braucht ihr keinen zweiten Artefakt-Speicher daneben, mit eigener Rechteverwaltung und eigenem Betriebsaufwand.

Referrers: etwas anhängen, ohne es anzufassen

Der zweite große Zugewinn aus Spec 1.1 heißt Referrers und löst ein Problem, das jeder kennt, der schon einmal ein SBOM zu einem Image ablegen musste: Wohin damit?

Bisher gab es zwei schlechte Antworten. Entweder ins Image hinein, dann ändert sich dessen Digest und die Signatur ist hinfällig. Oder daneben in ein anderes System, dann verliert man die Verbindung.

Referrers macht es anders. Zuerst ein SBOM erzeugen, hier mit Trivy:

trivy image --format cyclonedx --output sbom.json localhost:5000/alpine:3.22

Und dann an das Image hängen:

docker run --rm --network host -v "$PWD:/work" -w /work \
  ghcr.io/oras-project/oras:v1.3.0 \
  attach --plain-http --artifact-type application/vnd.cyclonedx+json \
  localhost:5000/alpine:3.22 sbom.json:application/json

Das erzeugte Manifest sieht aus wie das PDF von vorhin, mit einem entscheidenden Zusatz:

{
  "artifactType": "application/vnd.cyclonedx+json",
  "layers": [
    { "mediaType": "application/json", "size": 29208 }
  ],
  "subject": {
    "mediaType": "application/vnd.oci.image.manifest.v1+json",
    "digest": "sha256:7c8cb692ae09657cbc4a3f3cbd0e8d5a2690ba38386aaaf252dbb060bf5eb2e6",
    "size": 1022
  }
}

Das subject-Feld zeigt auf das Image. Das Image selbst bleibt dabei unverändert, sein Digest ist derselbe wie vorher. Die Beziehung entsteht einseitig, vom Anhang zum Original, und die Registry führt darüber Buch. Abfragen lässt sie sich über einen eigenen Endpunkt:

curl -s http://localhost:5000/v2/alpine/referrers/sha256:7c8cb692... | jq .

Zurück kommt ein Index aller Dinge, die an diesem Image hängen. Damit kann ein Image signiert bleiben und trotzdem im Nachhinein ein SBOM, eine Freigabe-Attestierung oder ein Prüfbericht dazukommen. Für alles, was der Cyber Resilience Act an Nachweisen über Lieferketten verlangen wird, ist das der Unterbau.

Die Spec ist das eine, deine Registry das andere

Beim Nachbauen bin ich über etwas gestolpert, das in den Erklärartikeln zu dem Thema meist fehlt. Der Referrers-Endpunkt aus der Distribution-Spec 1.1 ist nicht überall vorhanden. Lokal ergab dieselbe Abfrage gegen drei Registries drei verschiedene Antworten:

Registry Referrers-Endpunkt Tag-Liste danach
registry:2 404 enthält sha256-7c8cb692…
registry:3, Version 3.1.1 404 enthält sha256-7c8cb692…
zot 200, liefert einen Index nur 3.22

Bei den beiden ersten ist das kein Konfigurationsfehler. Die Antwort ist ein 404 page not found im Klartext, also die Standardantwort des HTTP-Routers und keine Fehlermeldung der Registry-API. Die Route existiert schlicht nicht.

Bei CNCF Distribution, der Referenz-Implementierung hinter beiden Images, ist die Umsetzung als Pull Request #4828 eingereicht und dem Meilenstein Registry 3.2.0 zugeordnet. Es ist der dritte Anlauf: Das zugehörige Proposal steht seit August 2022 offen, ein erster Versuch am Storage-Layer wurde nie übernommen. Ein Maintainer hat den Grund im März 2026 selbst benannt, und er ist weder technischer Streit noch Desinteresse:

There is no such thing as release cadence; I’m more or less one of the few maintainers who does this in my free time, free of charge.

Das ist die unbequeme Rückseite von Säule 2. Eine offene Lizenz nimmt dir niemand weg, aber sie stellt auch niemanden ab, der die Arbeit macht.

Das Tückische daran ist, dass zunächst nichts kaputtgeht. Wo der Endpunkt fehlt, weicht ORAS auf ein in der Spezifikation vorgesehenes Fallback aus und legt den Anhang unter einem Tag namens sha256-<digest> ab. Ein oras discover findet ihn danach trotzdem, und alles wirkt in Ordnung.

Der Preis steht in der rechten Spalte: Die Tag-Liste des Repositories füllt sich still mit Digest-Tags. Bei einem Image mit Signatur, SBOM und Attestierung sind das drei zusätzliche Tags pro Version. Wer dann Aufräumregeln nach Tag-Alter fährt, löscht irgendwann Attestierungen weg und wundert sich.

Ist so eine Registry überhaupt konform?

Die naheliegende Nachfrage, und die Antwort ist ein klares Ja. Die Distribution-Spezifikation teilt ihre Schnittstellen in vier Kategorien auf, und nur eine davon ist Pflicht:

Kategorie Status
Pull verbindlich für jede konforme Registry
Push optional
Content Discovery optional
Content Management optional

Die Referrers-API gehört zu Content Discovery und ist damit freiwillig. Wer eine optionale Kategorie beansprucht, muss sie vollständig umsetzen, aber niemand muss sie beanspruchen.

Genau deshalb sind der 404 und das Fallback kein Versehen, sondern in der Spezifikation vorgesehen. Sie schreibt vor, dass ein Client bei einem 404 auf das Tag-Schema ausweichen muss, und beim Hochladen eines Manifests mit subject erkennt er an einem fehlenden OCI-Subject-Antwortkopf, dass die Registry nicht mitspielt. Das ist sauber entworfen: Der Standard bleibt benutzbar, auch wenn eine Seite ein Stück davon nicht kann.

Der Preis dafür ist, dass „OCI-konform” auf einer Produktseite deutlich weniger verspricht, als es klingt. Es sagt zuverlässig, dass du Images ziehen kannst. Alles andere musst du nachfragen.

Und bei den großen Anbietern?

Die naheliegende Frage. Prüfen lässt sie sich ohne Anhänge, denn der Endpunkt antwortet auch bei leerem Ergebnis: HTTP 200 mit leerem Index heißt unterstützt, HTTP 404 heißt nicht unterstützt.

TOK=$(curl -s "https://auth.docker.io/token?service=registry.docker.io\
&scope=repository:library/alpine:pull" | jq -r .token)

curl -s -H "Authorization: Bearer $TOK" \
  "https://registry-1.docker.io/v2/library/alpine/referrers/sha256:14358309…" | jq .
Registry Referrers-API Grundlage
Docker Hub ja selbst getestet, HTTP 200
GitHub Container Registry nein selbst getestet, HTTP 404
Amazon ECR, privat ja, seit Juni 2024 Herstellerangabe
Azure Container Registry ja, außer bei CMK-Verschlüsselung Herstellerangabe
Google Artifact Registry ja, in Docker-Repositories Herstellerangabe

Die Cloud-Anbieter sind also weiter, als der lokale Versuch vermuten ließ. Drei Ergebnisse verdienen trotzdem einen zweiten Blick.

GHCR kann es nicht. Die Abfrage liefert ein klares 404 MANIFEST_UNKNOWN, während derselbe Digest über den Manifest-Endpunkt problemlos ausgeliefert wird. Der Digest ist also gültig, es fehlt wirklich der Endpunkt. Das gilt für öffentliche wie für private Pakete: Gegen ein privates Repository im eigenen Konto, angemeldet mit einem Token, das den Digest anstandslos auflöst, kommt dieselbe Antwort. Eine Frage von Sichtbarkeit oder Berechtigungen ist es also nicht. Bemerkenswert daran ist, dass ausgerechnet ORAS, Trivy und kubara ihre eigenen Artefakte über ghcr.io verteilen.

Und die Folge lässt sich dort direkt beobachten. Hängt man an ein Image auf GHCR ein SBOM, taucht in der Tag-Liste des Repositories anschließend genau das auf:

sha256-617cc95c6b7c93b482cd7474c8b9cfaf02be8991fad04948f43865d0c477992b

Ein Tag, der keiner Version entspricht, sondern der Digest des Images ist, an dem der Anhang hängt. Das Anhängen selbst hat funktioniert, ORAS findet den SBOM auch wieder. Nur liegt er eben nicht in einem Beziehungsindex, sondern in eurer Tag-Liste, wo ihr ihn nicht erwartet.

Bei ACR hängt es an der Verschlüsselung. Microsoft schreibt, die Referrers-API werde von den meisten ACR-Funktionen unterstützt, mit Ausnahme von Registries mit kundenverwalteten Schlüsseln. Dort fällt ORAS auf das Tag-Schema zurück. Wer aus Compliance-Gründen CMK einsetzt, bekommt also genau bei der Compliance-Funktion das Fallback.

Bei ECR gibt es eine offene Baustelle. Das rekursive Kopieren mit oras copy -r scheitert laut einem seit Monaten offenen Eintrag in der AWS-Roadmap an der Manifest-Prüfung. Ein Kopieren ohne -r gelingt, verliert dabei aber alle Referrer. Für eine Promotion-Kette von Dev nach Produktion ist das kein Randfall.

Daraus folgt die unbequemere Hälfte der guten Nachricht: Ein offener Standard garantiert, dass es geht. Nicht, dass deine Registry es kann. Bevor ihr eine Lieferketten-Strategie auf Referrers aufbaut, prüft den Endpunkt. Ein curl genügt, und die Antwort kostet euch dreißig Sekunden statt eines halben Projekts.

Damit ihr das nicht jedes Mal von Hand zusammenbauen müsst, habe ich die Prüfung als kleines Skript veröffentlicht: referrers-checker, Apache 2.0, kein CLA. Es löst den Tag auf, fragt den Endpunkt ab und sucht zusätzlich nach den Fallback-Tags. Nur lesende Zugriffe, es ist also auch gegen eine Produktions-Registry unbedenklich.

./referrers-check.sh ghcr.io/dein-konto/deine-app:1.0

Exit-Code 0 heißt unterstützt, 1 heißt nicht unterstützt. Damit lässt sich die Frage auch in einer Pipeline beantworten, statt sie einmal zu klären und wieder zu vergessen. Wenn ihr es gegen eine Registry laufen lasst, die in der Tabelle oben fehlt, freue ich mich über die Ausgabe als Issue.

Warum Docker das Format nicht zurückholen kann

Bleibt die Frage, warum das alles überhaupt so offen ist.

Die Antwort ist eine Entscheidung aus dem Jahr 2015. Damals gab Docker das Image-Format an die neu gegründete Open Container Initiative ab, zusammen mit der Laufzeitumgebung runc. Heute liegen Image-Spec, Runtime-Spec und Distribution-Spec unter Apache 2.0 bei der Linux Foundation, entwickelt in einem offenen Prozess.

Das klingt nach Formalie, ist aber der Grund für eine Beobachtung, die in dieser Blog-Reihe sonst selten vorkommt. Ich schreibe hier regelmäßig über Relizenzierungen: Redis wechselte 2024 auf eine quelloffene, aber nicht mehr freie Lizenz, HashiCorp tat dasselbe mit Terraform und Vault. In beiden Fällen war der Schmerz erheblich, weil an dem Produkt eine Menge hing.

Bei Containern ist dieser Hebel nicht vorhanden. Docker Inc. hat seine Lizenzbedingungen mehrfach verschärft, beim Desktop-Produkt und bei den Abrufgrenzen von Docker Hub. Am Format konnte das Unternehmen nichts ändern, weil es ihm nicht mehr gehört. Deshalb bauen Podman, Buildah, Kaniko und containerd dieselben Images, deshalb liest jede Registry dieselben Manifeste, und deshalb ist ein Wechsel des Anbieters hier Fleißarbeit statt Migration.

Das ist die zweite Säule in ihrer angenehmsten Form. Sonst muss man Lizenzen prüfen, um Schaden abzuwenden. Hier hat jemand vor elf Jahren die Arbeit gemacht, und der Ertrag ist, dass eine ganze Werkzeugschicht austauschbar ist, ohne dass es jemandem auffällt.

Der Umkehrschluss taugt als Prüffrage für jede neue Technologie in eurem Stack: Gibt es eine offene Spezifikation, oder gibt es nur eine Implementierung? Bei Containern ist die Antwort erfreulich. Bei vielem, was gerade als Plattform verkauft wird, nicht.

Fazit

  1. Eine Registry kennt keine Images. Sie kennt Manifeste, Deskriptoren und Blobs, und ein Image ist der bekannteste Sonderfall.
  2. Ein beliebiger Dateityp wird zum OCI-Artefakt, indem er als Layer mit eigenem Medientyp abgelegt wird, der Config-Deskriptor leer bleibt und artifactType die Bedeutung trägt.
  3. Das ist keine Spielerei: Helm-Charts, Trivys Schwachstellen-DB, kubaras Kataloge, Sigstore-Signaturen und Policy-Bundles nutzen alle diesen Weg, auf der Infrastruktur, die ihr ohnehin betreibt.
  4. Referrers hängt SBOMs und Attestierungen über das subject-Feld an ein Image, ohne dessen Digest zu verändern. Das ist der Unterbau für Lieferketten-Nachweise.
  5. Prüft den Referrers-Endpunkt eurer Registry, bevor ihr darauf baut. Docker Hub, ECR, ACR und Artifact Registry können es, GHCR und CNCF Distribution nicht. Das ist zulässig, denn Content Discovery ist eine optionale Kategorie der Spezifikation. Genau deshalb sagt die Aussage „OCI-konform” allein noch nichts darüber aus.

Die Registry, die bei euch seit Jahren Images verteilt, ist in Wahrheit ein allgemeiner, inhaltsadressierter Artefaktspeicher mit Rechteverwaltung und Replikation. Ihr müsst ihn nur so benutzen. Und dass das geht, ohne jemanden um Erlaubnis zu fragen, verdankt ihr einer Spezifikation, die keinem Hersteller gehört.

© 2026 Trutz Software Consulting GmbH. CC BY 4.0: Dieser Text darf mit Namensnennung weiterverwendet und bearbeitet werden, auch kommerziell. Code-Beispiele darin stehen unter Apache 2.0. Ausgenommen sind Marke und Logo sowie gekennzeichnete Zitate Dritter. Was das genau heißt.

Newsletter

Erhalte praxisnahe Tutorials, Best Practices und echte Lösungen für die häufigsten DevOps-Probleme direkt in Dein Postfach.

Datenschutz: Deine E-Mail-Adresse wird DSGVO-konform in Deutschland gespeichert. Keine Spam, nur relevante Inhalte. Eine E-Mail alle 1 bis 2 Wochen.