von der privaten Registry bis zum Image-Lifecycle
Eine unkontrollierte Flut aus latest-Tags und anonymen Docker-Hub-Pulls gefährdet jede Produktionsumgebung. Wer eine private Docker Registry betreibt, sinnvolle Image-Versionen einführt und Retention-Policies definiert, schafft nachvollziehbare, reproduzierbare Builds und reduziert Ausfallrisiken erheblich.
Inhaltsverzeichnis
- 1. Warum eine eigene Docker Registry sinnvoll ist
- 2. Distribution Registry in fünf Minuten starten
- 3. TLS und Basic-Auth absichern
- 4. Sinnvolle Tags und Semantic Versioning
- 5. Images in der CI-Pipeline taggen und pushen
- 6. Image-Retention und Garbage Collection
- 7. Harbor als Enterprise-Alternative
- 8. GitHub Container Registry als leichtgewichtige Option
- 9. Registries im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Warum eine eigene Docker Registry sinnvoll ist
Wer alle Images direkt von Docker Hub bezieht, akzeptiert mehrere versteckte Risiken gleichzeitig. Docker Hub drosselt anonyme Pulls auf 100 Requests pro sechs Stunden – in größeren Teams oder CI-Umgebungen mit vielen parallelen Builds führt das zu zufälligen Buildfehlern, die schwer zu diagnostizieren sind. Eine private Docker Registry beseitigt diese Abhängigkeit vollständig, weil alle Images lokal vorgehalten werden und jeder Pull innerhalb der eigenen Infrastruktur stattfindet.
Darüber hinaus bietet eine eigene Docker Registry volle Kontrolle darüber, welche Images im Umlauf sind. In regulierten Umgebungen – etwa mit Datenschutzanforderungen oder Compliance-Vorgaben – dürfen keine beliebigen Base-Images aus dem Internet verwendet werden. Die Registry wird zum Single Point of Trust: Jedes Image, das in die Produktion gelangt, muss aus dem eigenen Repository stammen, ist geprüft und versioniert. Das macht Audits deutlich einfacher und Sicherheitslücken besser nachverfolgbar.
2. Distribution Registry in fünf Minuten starten
Die offizielle Distribution Registry (früher bekannt als Docker Registry v2) ist ein schlankes Go-Programm, das als Docker Image auf Docker Hub verfügbar ist. Sie benötigt keine Datenbank, speichert alle Image-Layer als Dateien und ist damit trivial zu betreiben. Für interne Entwicklungsumgebungen reicht ein einziger docker compose up-Befehl, um eine funktionsfähige Docker Registry zu starten, die sofort für Push- und Pull-Operationen bereit ist.
Die Registry horcht standardmäßig auf Port 5000. Um ein Image dorthin zu pushen, muss der Imagename den Registry-Host als Präfix enthalten: registry.local:5000/meinprojekt/api:1.2.0. Docker unterscheidet Registries anhand dieses Präfixes – fehlt es, nimmt Docker Hub an. Mit einem lokalen DNS-Eintrag oder einem Eintrag in /etc/hosts lässt sich ein sprechender Hostname wie registry.local vergeben, statt immer die IP-Adresse zu tippen. Das spart Tipp-Fehler und macht die Konfiguration lesbarer.
# compose.registry.yml — Local Docker Registry with persistent storage
services:
registry:
image: registry:2.8
container_name: docker-registry
restart: unless-stopped
ports:
- "5000:5000"
environment:
# Store images in a named volume for persistence
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
# Enable deletion API (needed for garbage collection later)
REGISTRY_STORAGE_DELETE_ENABLED: "true"
# Log level: debug, info, warn, error
REGISTRY_LOG_LEVEL: info
volumes:
- registry-data:/var/lib/registry
- ./registry/config.yml:/etc/docker/registry/config.yml:ro
volumes:
registry-data:
driver: local
# Push an image to the local registry:
# docker tag myapp:latest registry.local:5000/myapp:1.0.0
# docker push registry.local:5000/myapp:1.0.0
# List repositories via API:
# curl http://registry.local:5000/v2/_catalog
Die Registry-API folgt der OCI Distribution Specification und ist vollständig dokumentiert. Mit einem einfachen curl-Aufruf lassen sich alle vorhandenen Repositories auflisten und die verfügbaren Tags eines Images abfragen. Das ist nützlich für Monitoring-Skripte, die prüfen, ob ein bestimmtes Image in der erwarteten Version vorhanden ist, bevor ein Deployment gestartet wird.
3. TLS und Basic-Auth absichern
Eine Docker Registry ohne TLS akzeptiert Docker nur als explizit konfigurierte "insecure registry". Das ist für Laptops und lokale Tests akzeptabel, für geteilte Infrastruktur aber ein ernsthaftes Problem: Credentials und Image-Layer werden im Klartext übertragen. TLS lässt sich entweder direkt in der Registry konfigurieren oder – was flexibler ist – durch einen vorgelagerten Reverse-Proxy wie Nginx oder Traefik bereitstellen. Dieser Ansatz hat den Vorteil, dass die Registry selbst einfach konfiguriert bleibt und der Proxy TLS-Termination für mehrere Services übernehmen kann.
Basic-Auth für die Registry wird ebenfalls am bequemsten im Proxy konfiguriert. Das htpasswd-Format kennt Docker nativ: Mit htpasswd -Bc /auth/htpasswd username wird ein Benutzer angelegt, die Datei in den Proxy-Container gemountet. Für feingranularere Zugriffssteuerung – bestimmte Benutzer dürfen nur bestimmte Repositories lesen – ist die offizielle Registry etwas eingeschränkt. Harbor oder die GitHub Container Registry bieten hier deutlich mehr Möglichkeiten. Für Teams ab fünf Personen lohnt der Wechsel zu einer vollständigen Registry-Plattform meistens mehr als das Selbst-Konfigurieren von Autorisierungs-Plugins.
# nginx-registry.conf — TLS termination and Basic-Auth for Docker Registry
# Place in /etc/nginx/conf.d/registry.conf
server {
listen 443 ssl http2;
server_name registry.example.com;
# TLS certificates (use mkcert for local dev or Let's Encrypt for production)
ssl_certificate /etc/nginx/certs/registry.crt;
ssl_certificate_key /etc/nginx/certs/registry.key;
# Increase max body size — Docker layers can be several hundred MB
client_max_body_size 2000m;
# Basic-Auth protection
auth_basic "Docker Registry";
auth_basic_user_file /etc/nginx/auth/htpasswd;
location / {
# Proxy to the registry container (must be on same Docker network)
proxy_pass http://registry:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Chunked transfer for large uploads
proxy_request_buffering off;
proxy_read_timeout 600;
}
}
4. Sinnvolle Tags und Semantic Versioning
Das latest-Tag ist in der Produktion ein Anti-Pattern. Es gibt keine Auskunft darüber, wann das Image gebaut wurde, welchen Code-Stand es enthält oder ob es sich seit dem letzten Deployment verändert hat. Ein Deployment mit latest ist nicht reproduzierbar, weil ein späterer Pull eine andere Version liefern kann als der ursprüngliche. Die Lösung ist konsequentes Image-Versionieren nach Semantic Versioning: 1.2.3 für stabile Releases, 1.2.3-rc.1 für Release Candidates und 1.2.3-dev.abc1234 für Feature-Branches.
Zusätzlich zu Semantic-Version-Tags empfehlen sich unveränderliche Content-Hash-Tags auf Basis des Git-Commits: sha-abc1234. Dieses Tag verändert sich nie und identifiziert exakt, welchen Commit das Image enthält. In CI-Pipelines baut man üblicherweise beides gleichzeitig: ein sprechendes Versions-Tag und ein Git-SHA-Tag. Das Versions-Tag zeigt auf das aktuellste Image einer Version, das SHA-Tag macht das Image dauerhaft über seinen Ursprung auffindbar. Kubernetes und andere Orchestratoren sollten immer SHA-Tags verwenden, um versehentliches Überschreiben bei Rollouts zu verhindern.
5. Images in der CI-Pipeline taggen und pushen
In modernen CI/CD-Systemen wie GitHub Actions, GitLab CI oder Drone ist das Bauen und Pushen von Docker Images eine Standard-Operation. Die Herausforderung liegt im konsequenten Tagging: Das Image soll sowohl mit einem sprechenden Versions-Tag als auch mit dem Git-SHA getaggt werden. Docker ermöglicht es, einem Image beliebig viele Tags zu geben – alle zeigen auf denselben Layer-Stack und verursachen keinen zusätzlichen Speicher in der Registry. Das Taggen in der CI-Pipeline kostet also nichts außer ein paar Millisekunden für die Push-Operationen.
Eine wichtige Praxis ist das Multi-Platform-Building mit docker buildx. Wer Images sowohl für linux/amd64 als auch für linux/arm64 benötigt – etwa weil Entwickler auf Apple-Silicon-Macs arbeiten und die Produktion auf x86-Servern läuft – baut beide Varianten in einer einzigen Pipeline und pusht sie als Multi-Arch-Manifest. Der Pull-Client bekommt dann automatisch das passende Image für seine Architektur geliefert, ohne dass eine Unterscheidung im Imagenahmen nötig ist.
#!/usr/bin/env bash
# ci-build-push.sh — Build, tag and push Docker image in CI
set -euo pipefail
# Read version from git or environment variable
GIT_SHA="$(git rev-parse --short HEAD)"
GIT_TAG="${CI_TAG:-}"
REGISTRY="${REGISTRY:-registry.example.com}"
IMAGE_NAME="${IMAGE_NAME:-myapp}"
# Determine version tag
if [[ -n "$GIT_TAG" ]]; then
VERSION_TAG="$GIT_TAG"
else
# Feature branch: use branch name + sha
BRANCH="${CI_BRANCH:-$(git rev-parse --abbrev-ref HEAD)}"
SAFE_BRANCH="${BRANCH//\//-}"
VERSION_TAG="${SAFE_BRANCH}-${GIT_SHA}"
fi
FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}"
# Build multi-platform image with buildx
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag "${FULL_IMAGE}:${VERSION_TAG}" \
--tag "${FULL_IMAGE}:sha-${GIT_SHA}" \
--cache-from "type=registry,ref=${FULL_IMAGE}:buildcache" \
--cache-to "type=registry,ref=${FULL_IMAGE}:buildcache,mode=max" \
--push \
.
echo "Pushed: ${FULL_IMAGE}:${VERSION_TAG}"
echo "Pushed: ${FULL_IMAGE}:sha-${GIT_SHA}"
6. Image-Retention und Garbage Collection
Ohne aktives Management wächst eine Docker Registry unbegrenzt. Jeder Build fügt neue Layer hinzu, alte Tags werden selten manuell gelöscht, und nach einem Jahr hat die Registry mehrere Hundert Gigabyte belegt. Image-Retention-Policies definieren, wie viele Versionen eines Images behalten werden und ab wann alte Tags gelöscht werden dürfen. Die Distribution Registry selbst bietet keine eingebauten Retention-Policies – das Löschen von Tags muss über die API oder externe Tools wie docker-registry-pruner gesteuert werden.
Wichtig: In der Distribution Registry sind gelöschte Tags zunächst nur als Manifest-Einträge entfernt; die eigentlichen Layer-Daten (Blobs) bleiben auf der Festplatte. Erst die Garbage Collection – registry garbage-collect /etc/docker/registry/config.yml – entfernt nicht mehr referenzierte Blobs und gibt Speicher frei. Dieser Prozess läuft idealerweise nachts als Cronjob und sollte während der Laufzeit im Read-Only-Modus ausgeführt werden, um Datenkonsistenz zu wahren. Harbor automatisiert diese Schritte vollständig und bietet eine Web-UI zur Konfiguration von Retention-Regeln.
7. Harbor als Enterprise-Alternative
Harbor ist eine CNCF-Projekt-graduierte Open-Source-Registry-Plattform, die weit über die Funktionen der Distribution Registry hinausgeht. Sie bietet rollenbasierte Zugriffssteuerung auf Projekt-Ebene, integriertes Vulnerability-Scanning mit Trivy oder Clair, Image-Signierung mit Notary, automatische Retention-Policies und eine vollständige Web-Oberfläche. Für Teams, die mehrere Projekte mit unterschiedlichen Zugriffsberechtigungen verwalten, ist Harbor die überzeugendste Self-Hosted-Option.
Der Betrieb von Harbor erfordert mehr Infrastruktur als die schlichte Distribution Registry: Harbor benötigt eine PostgreSQL-Datenbank, einen Redis-Cache und mehrere eigene Microservices. Die offizielle harbor-installer-Distribution bringt ein Compose-Setup mit, das alle Komponenten zusammenfasst. Für Produktionsumgebungen empfiehlt sich ein Kubernetes-Deployment per Helm-Chart, das Rolling Updates ohne Downtime ermöglicht. Das Vulnerability-Scanning läuft asynchron nach jedem Push und blockiert Deployments von Images mit kritischen CVEs, wenn die entsprechende Policy aktiv ist.
8. GitHub Container Registry als leichtgewichtige Option
Die GitHub Container Registry (GHCR) ist für Teams, die GitHub für Source-Control und CI verwenden, die naheliegendste private Docker Registry-Alternative ohne eigenen Infrastrukturaufwand. Images werden unter ghcr.io/organisation/imagename:tag gespeichert und teilen die Zugriffsberechtigungen des GitHub-Repositories. Ein Repository-Maintainer kann automatisch Images pushen, während externe Contributor nur Pull-Zugriff haben – ohne zusätzliche Konfiguration.
GHCR unterstützt OCI-Artifacts, was bedeutet, dass nicht nur Docker Images, sondern auch Helm-Charts, WASM-Module und andere Artefakte in derselben Registry gespeichert werden können. Für Open-Source-Projekte sind public Packages kostenlos, für private Packages ist Speicherplatz im GitHub-Plan enthalten. Der einzige relevante Nachteil gegenüber einer selbst gehosteten Registry ist die Abhängigkeit von der GitHub-Infrastruktur – bei GitHub-Ausfällen sind auch die eigenen Images nicht erreichbar.
9. Registries im Vergleich
Die Wahl der richtigen Docker Registry hängt von Teamgröße, Compliance-Anforderungen und vorhandener Infrastruktur ab. Es gibt keine universell beste Lösung – jede Option hat klare Stärken und Einschränkungen.
| Registry | Hosting | Zugriffssteuerung | Besonderheit |
|---|---|---|---|
| Distribution Registry | Self-Hosted | Basic-Auth via Proxy | Minimal, kein UI, kein Scanning |
| Harbor | Self-Hosted | RBAC, OIDC, LDAP | Scanning, Signierung, Retention-UI |
| GHCR | GitHub-Managed | GitHub-Berechtigungen | OCI-Artifacts, kein Infrastruktur-Aufwand |
| AWS ECR | AWS-Managed | IAM-Policies | Native ECS/EKS-Integration, Lifecycle-Policies |
| Docker Hub | Docker-Managed | Teams, Organisationen | Pull-Rate-Limit bei anonymen Requests |
Für Einzelentwickler und kleine Teams ohne Compliance-Anforderungen ist GHCR die einfachste Wahl, sofern GitHub bereits genutzt wird. Mittlere Teams mit eigenem Server und dem Wunsch nach voller Kontrolle greifen zu Harbor. Wer bereits in AWS-Infrastruktur investiert hat, sollte ECR wegen der nativen IAM-Integration bevorzugen. Die Distribution Registry eignet sich hauptsächlich als Cache oder für vollständig airgapped Umgebungen ohne Internetzugang.
Mironsoft
Docker-Infrastruktur, Registry-Setup und CI/CD-Integration
Eigene Docker Registry aufsetzen und Images sauber versionieren?
Wir richten private Registries ein, definieren Tagging-Strategien, integrieren Vulnerability-Scanning und automatisieren den gesamten Image-Lifecycle in eurer CI/CD-Pipeline.
Registry-Setup
Distribution Registry, Harbor oder GHCR – je nach Anforderung aufsetzen und absichern
Tagging-Strategie
Semantic Versioning und Git-SHA-Tags konsequent in alle CI-Pipelines integrieren
Lifecycle-Management
Retention-Policies, Garbage Collection und Monitoring für die Registry automatisieren
10. Zusammenfassung
Eine eigene Docker Registry löst drei Kernprobleme gleichzeitig: Rate-Limits von Docker Hub entfallen, alle Images sind intern versioniert und nachvollziehbar, und Compliance-Anforderungen hinsichtlich Datenhaltung lassen sich erfüllen. Die Distribution Registry ist der schnellste Einstieg, Harbor bietet Enterprise-Features für größere Teams, GHCR ist die reibungsloseste Option für GitHub-Nutzer. Die Wahl der Plattform ist zweitrangig – wichtiger ist die konsequente Einführung einer Tagging-Strategie.
Semantic-Version-Tags kombiniert mit Git-SHA-Tags ergeben eine vollständig nachvollziehbare Image-Historie. Jedes Deployment lässt sich auf einen konkreten Git-Commit zurückführen. Garbage Collection und Retention-Policies verhindern unkontrolliertes Registry-Wachstum. Mit diesen drei Bausteinen – sinnvolle Registry, klare Tags, aktives Lifecycle-Management – ist die Docker Registry kein Flaschenhals mehr, sondern ein zuverlässiges Fundament der Deployment-Pipeline.
Docker Registry und Image-Versionierung — Das Wichtigste auf einen Blick
Registry-Wahl
Distribution Registry für minimale Setups, Harbor für RBAC und Scanning, GHCR für GitHub-Teams, ECR für AWS-native Stacks.
Tagging-Strategie
Kein latest in der Produktion. Semantic Versioning (1.2.3) kombiniert mit Git-SHA-Tags (sha-abc1234) für vollständige Nachvollziehbarkeit.
Absicherung
TLS per Reverse-Proxy, Basic-Auth oder OIDC. Keine Registry ohne Authentifizierung im Netzwerk exponieren.
Lifecycle
Retention-Policies und Garbage Collection als Cronjob. Ohne aktives Management wächst die Registry unkontrolliert auf mehrere Hundert GB.