Eigene Docker-Registry betreiben - Images intern hosten

Eigene Docker-Registry betreiben - Images intern hosten

Mit dem offiziellen registry:2-Image lässt sich in wenigen Minuten eine private Docker-Registry betreiben — ohne Docker Hub, ohne externe Abhängigkeiten.

Warum eine eigene Registry?

  • Datenschutz: Proprietary Images verlassen das eigene Netzwerk nicht
  • Geschwindigkeit: Pulls aus dem lokalen Netzwerk statt aus dem Internet
  • Air-Gap: Betrieb ohne Internetzugang möglich
  • Rate Limits: Kein Docker Hub Pullimit

Einfacher Start

docker run -d \
  -p 5000:5000 \
  --name registry \
  --restart unless-stopped \
  -v ./registry-data:/var/lib/registry \
  registry:2

Die Registry läuft jetzt auf Port 5000 und speichert Images im Verzeichnis ./registry-data.

Images pushen

# Image aus Docker Hub holen
docker pull nginx:1.25

# Für die lokale Registry taggen
docker tag nginx:1.25 localhost:5000/nginx:1.25

# Pushen
docker push localhost:5000/nginx:1.25

# Auf anderen Hosts (TLS nötig oder insecure-registries):
docker tag nginx:1.25 192.168.1.10:5000/nginx:1.25
docker push 192.168.1.10:5000/nginx:1.25

Images in der Registry auflisten

Die Registry bietet eine HTTP-API:

# Alle Images
curl http://localhost:5000/v2/_catalog

# Tags eines Images
curl http://localhost:5000/v2/nginx/tags/list

Authentifizierung mit htpasswd

# htpasswd-Datei erstellen
docker run --rm httpd htpasswd -Bbn myuser mypassword > auth/htpasswd

# Registry mit Auth starten
docker run -d \
  -p 5000:5000 \
  --name registry \
  -v ./registry-data:/var/lib/registry \
  -v ./auth:/auth \
  -e REGISTRY_AUTH=htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_REALM="Docker Registry" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  registry:2

TLS für externe Nutzung

Ohne TLS akzeptiert Docker Verbindungen zu einer Remote-Registry nur, wenn sie als insecure-registry konfiguriert ist. Die saubere Lösung ist Caddy als TLS-Proxy:

services:
  registry:
    image: registry:2
    volumes:
      - ./registry-data:/var/lib/registry
    # Kein Port-Mapping nötig — Caddy spricht intern mit dem Container

  caddy:
    image: caddy:latest
    ports:
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy-data:/data

Caddyfile:

registry.example.com {
    reverse_proxy registry:5000
}

Caddy holt automatisch ein Let's Encrypt-Zertifikat.

Insecure Registry (lokales Netz, kein TLS)

In /etc/docker/daemon.json auf dem Client-Host:

{
  "insecure-registries": ["192.168.1.10:5000"]
}
sudo systemctl restart docker

Grafisches Frontend

Wer eine Web-UI möchte:

  registry-ui:
    image: joxit/docker-registry-ui:latest
    ports:
      - "8080:80"
    environment:
      REGISTRY_URL: http://registry:5000
      DELETE_IMAGES: "true"

Zusammenfassung

Eine private Registry mit registry:2 ist in unter 5 Minuten betriebsbereit. Für den lokalen Einsatz reicht der einfache Start ohne TLS. Für den Einsatz über das Internet: Caddy als TLS-Proxy vorschalten und htpasswd-Authentifizierung aktivieren.