Eigene Docker-Registry für Images installieren

Eigene Docker-Registry für Images installieren

Docker bietet offizielle Images, um eine eigene Registry zu hosten. Dadurch ist man nicht vom externen Docker-Hub abhängig. Dies kann auch für sicherheitskritische Images eine Option sein, die man nicht extern hosten möchte. Aber auch ein interner Kubernetes-Cluster ist ein Beispiel-Szenario, in dem Docker-Images gebaut und auf einer Registry abgelegt werden können. Durch die Nutzung einer internen Registry muss keine Internetverbindung seitens der Cluster-Server hergestellt werden.

Docker-Registry installieren

Das Deployment einer eigenen Registry ist recht einfach. Eine Out-of-the-Box Installation kann mit einem einzigen docker run Befehl innerhalb weniger Sekunden gestartet werden:

docker run -d -p 5000:5000 --restart always --name registry registry:2

Die Registry ist nun auf dem Hostsystem über Port 5000 erreichbar. Mit curl können wir eine Testabfrage senden und sehen – wie erwartet – noch keine Repositorys, erhalten aber eine JSON-Antwort:

$ curl http://localhost:5000/v2/_catalog
{"repositories":[]}

Docker-Registry installieren

docker run -d -p 5000:5000 --restart always --name registry registry:2

Die Registry ist nun auf dem Hostsystem über Port 5000 erreichbar. Mit curl können wir eine Testabfrage senden und sehen – wie erwartet – noch keine Repositorys, erhalten aber eine JSON-Antwort:

$ curl http://localhost:5000/v2/_catalog
{"repositories":[]}

In den Standardeinstellungen wird keine Authentifizierung gesetzt. Somit kann jeder Images pullen und pushen. Während dies für Testzwecke ausreicht, sollte man eine produktive Installation mittels Passwort schützen. Abgesehen davon läuft auf der Maschine nun eine Registry, in die man beliebig Pushen kann.

Erweiterte Registry-Konfiguration via YAML

Die Docker-Registry bietet eine ganze Reihe von Einstellungsmöglichkeiten. Beispielsweise kann der Speicherort und Typ für Images angepasst, ein Zugangsschutz eingerichtet und Redis als Cache-Speicher eingesetzt werden. Für diese Optionen kommt das YAML-Format zum Einsatz. Docker selbst bietet eine ausführliche Dokumentation mit Erläuterungen und Beispielen hierzu an. Das minimalistische Beispiel ist eine gute Grundlage. Hier ist auch bereits die Authentifizierung mit eingebaut:

version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
auth:
  htpasswd:
    realm: basic-realm
    path: /etc/registry
health:
  storagedriver:
    enabled: true
    interval: 10s
threshold: 3

BASIC Authentifizierung aktivieren

Die .htpasswd Datei müssen wir noch generieren. Das htpasswd CLI-Tool ist im Debian-Paket apache2-utils enthalten. Wer es nicht auf dem Hostsystem installiert hat, kann auch einfach das bereits installierte im Container nutzen:

docker exec -it registry htpasswd -B -b -c /etc/registry test test

Generiert den Nutzer test mit dem Passwort test. Zu beachten ist, dass das Passwort hier ggf. für andere User auf dem System in der Prozessübersicht sichtbar ist. Sofern händisch generiert wird, sollte man daher den 2. Parameter des Passwortes zusammen mit dem -b Schalter weglassen. Dann wird das Passwort abgefragt. Wichtig ist jedoch der Schalter -B, der BCrypt aktiviert – dies ist derzeit die einzige von Docker unterstützte methode.

Nun haben wir die htpasswd-Datei zwar im Container. Da dieser allerdings flüchtig ist, existiert diese nach dem nächsten Neustart nicht mehr. Daher exportieren wir die erzeugte Datei auf den Host:

docker exec -it registry cat /etc/registry >> registry-htpasswd

Damit die Konfiguration greift, ist ein Neustart des Containers erforderlich.

docker rm -vf registry
docker run -d -p 5000:5000 --restart always --name registry \
    -v $(pwd)/registry-htpasswd:/etc/registry \
    -v $(pwd)/config.yml:/etc/docker/registry/config.yml \
    registry:2

Authentifizierung testen

Wird die Registry nach dem Neustart per curl aufgerufen, erhalten wir im Erfolgsfall eine Fehlermeldung. Klingt Paradox, aber da wir die Authentifizierung eingeschaltet haben, darf uns die Registry nicht mehr ohne Login antworten:

$ curl http://localhost:5000/v2/_catalog
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Class":"","Name":"catalog","Action":"*"}]}]}

Mit den Zugangsdaten test:test sollten wir in diesem Beispiel Zugriff erhalten, d.H. die leere Repository-Liste:

$ curl http://localhost:5000/v2/_catalog --user test:test
{"repositories":[]}

Leave a Reply