Ein Container-Registry ist ein Speicherkatalog, von dem aus Container-Images hochgeladen und abgerufen werden können.

Es gibt viele öffentliche und private Registries, die Entwicklern zur Verfügung stehen, wie z.B. Docker Hub, Amazon ECR und Google Cloud Artifact Registry. Aber manchmal möchte man sich lieber nicht auf einen externen Anbieter verlassen und die eigenen Images selbst verwalten. Dies gibt einem mehr Kontrolle über die Konfiguration des Registries und das Hosting der Container-Images.

Dieser Artikel ist ein praktisches Tutorial, das Ihnen beibringt, wie man ein eigenes Container-Registry betreiben kann.

Inhaltsverzeichnis

Du kannst dieser Artikel am besten ausnutzen, wenn du bereits mit Tools wie Docker und NGINX vertraut bist und ein allgemeines Verständnis von was ein Container ist.

Was ist ein Containerimage?

Vor dem Inhalt über Containerregistries reden, lerne uns zunächst, was ein Containerimage ist. Eines kurz gesagt ist es ein Paket, das alle Dateien, Bibliotheken und Konfigurationen enthält, um einen Container zu betreiben. Sie bestehen aus Ebenen, wobei jede Ebene ein Set von Dateisystemänderungen repräsentiert, die Dateien hinzufügen, entfernen oder ändern.

Der am häufigsten verwendete Weg, um ein Containerimage zu erstellen, besteht darin, ein Dockerfile zu verwenden.

# build an image
docker build -t pliutau/hello-world:v0 .

# check the images locally
docker images
# REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
# hello-world   latest    9facd12bbcdd   22 seconds ago   11MB

Dadurch wird ein Container-Image erstellt, das auf Ihrem lokalen Rechner gespeichert wird. Aber was passiert, wenn Sie dieses Image mit anderen teilen oder auf einem anderen Rechner verwenden möchten? Hier kommt das Container-Registrieren ins Spiel.

Was ist ein Container-Registrieren?

Ein Container-Registrierung ist ein Speicherkatalog, in dem Sie Container-Images hoch- und herunterladen können. Die Images werden in Repositories gruppiert, die Sammlungen von verwandten Images mit demselben Namen sind. Zum Beispiel ist auf dem Docker Hub Registry der Name nginx des Repositories, das verschiedene Versionen der NGINX-Images enthält.

Einige Registrierungen sind öffentlich, was bedeutet, dass die auf ihnen gehosteten Images für jeden über das Internet zugänglich sind. Öffentliche Registrierungen wie der Docker Hub sind eine gute Option, um Open-Source-Projekte zu hosten.

Andersseits bieten private Registrierungen eine Möglichkeit, Sicherheit und Privatsphäre in die Enterprise-Containerimage-Speicherung einzubinden, entweder in der Cloud oder auf demselben Server. Diese private Registrierungen haben oft fortschrittliche Sicherheitsfunktionen und technische Unterstützung.

Es gibt eine wachsende Liste von privaten Registriern, wie z.B. der Amazon ECR, der GCP Artifact Registry, der GitHub Container Registry und Docker Hub bietet auch eine private Repository-Funktion an.

Als Entwicklerinteragieren Sie mit einem Containerregistrierung, wenn Sie die Befehle docker push und docker pull verwenden.

docker push docker.io/pliutau/hello-world:v0

# Im Falle von Docker Hub könnten wir die Registry-Komponente auch überspringen
docker push pliutau/hello-world:v0

Lassen Sie uns die Anatomie einer Containerimage-URL anschauen:

docker pull docker.io/pliutau/hello-world:v0@sha256:dc11b2...
                |            |            |          |
                ↓            ↓            ↓          ↓
             registry    repository      tag       digest

Warum Sie selbst einen Containerregistrierung hosten könnten interessant sein

Manchmal ist es interessanter, anstatt auf einen Anbieter wie AWS oder GCP zu greifen, selbst Ihre Bilder zu hosten. Dies bewahrt Ihre Infrastruktur intern auf und macht Sie abhängiger von externen Anbietern. In einigen strengen regulierten Branchen ist das sogar eine Voraussetzung.

Eine selbstgehostete Registry läuft auf Ihren eigenen Servern und gibt Ihnen mehr Kontrolle über die Konfiguration der Registry und den Hostingort der Containerimages. Gleichzeitig kommt dies mit dem Aufwand der Wartung und Sicherung der Registry.

Wie man eine Containerregistrierung selbsthostet

Es gibt verschiedene Open-Source-Containerregistrierungslösungen. Die am meisten populäre Lösung wird offiziell von Docker unterstützt und heißt registry, mit seiner Implementierung zur Speicherung und Verteilung von Containerimages und Artefakten. Dies bedeutet, dass Sie Ihre eigene Registry innerhalb eines Containers ausführen können.

Hier sind die HauptSchritte, um eine Registry auf einem Server zu betreiben:

  • Installieren Sie Docker und Docker Compose auf dem Server.

  • Konfigurieren und starten Sie den registry-Container.

  • Führe NGINX aus, um TLS zu verwalten und Anfragen an den Registry-Container weiterzuleiten.

  • Lege SSL-Zertifikate auf und richte ein Domain-Verzeichnis ein.

Schritt 1: Installiere Docker und Docker Compose auf dem Server

Du kannst jeder Server verwenden, der Docker unterstützt. Zum Beispiel kannst du ein DigitalOcean Droplet mit Ubuntu verwenden. Für diese Demo habe ich ein VM mit Ubuntu auf Google Cloud Compute erstellt.

neofetch

# Betriebssystem: Ubuntu 20.04.6 LTS x86_64
# CPU: Intel Xeon (2) @ 2.200GHz
# Speicher: 3908MiB

Sobald wir uns in unserem VM befinden, sollten wir Docker und Docker Compose installieren. Docker Compose ist optional, macht es jedoch einfacher, mehrere-Container-Anwendungen zu verwalten.

# installiere Docker Engine und docker-compose
sudo snap install docker

# überprüfe die Installation
docker --version
docker-compose --version

Schritt 2: Konfiguriere und führe den Registry-Container aus

Nächstes müssen wir unseren Registry-Container konfigurieren. Die folgende compose.yaml Datei wird einen Registry-Container mit einem Datenträger für das Speichern von Bildern und einem Datenträger für das Speichern des Passwortdateien erzeugen.

services:
  registry:
    image: registry:latest
    environment:
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      # Einhängen der Passwortdatei
      - ./registry/registry.password:/auth/registry.password
      # Einhängen des Datenverzeichnisses
      - ./registry/data:/data
    ports:
      - 5000

Die Passwortdatei, die in REGISTRY_AUTH_HTPASSWD_PATH definiert ist, wird verwendet, um Benutzer zu authentifizieren, wenn sie Images aus der Registry pushen oder ziehen. Wir sollten eine Passwortdatei mit dem Befehl htpasswd erstellen. Wir sollten auch einen Ordner zum Speichern der Images erstellen.

mkdir -p ./registry/data

# install htpasswd
sudo apt install apache2-utils

# create a password file. username: busy, password: bee
htpasswd -Bbn busy bee > ./registry/registry.password

Jetzt können wir den Registry-Container starten. Wenn Sie diese Meldung sehen, dann funktioniert alles wie es sollte:

docker-compose up

# successfull run should output something like this:
# registry | level=info msg="listening on [::]:5000"

Schritt 3: NGINX für die Verarbeitung von TLS ausführen

Wie bereits erwähnt, können wir NGINX für die Verarbeitung von TLS und die Weiterleitung von Anfragen an den Registry-Container verwenden.

Die Docker Registry benötigt ein gültiges vertrauenswürdiges SSL-Zertifikat, um zu funktionieren. Sie können etwas wie Let’s Encrypt verwenden oder es manuell beschaffen. Stellen Sie sicher, dass Sie einen Domainnamen haben, der auf Ihren Server zeigt (registry.pliutau.com in meinem Fall). Für diese Demo habe ich die Zertifikate bereits mit certbot bezogen und in das Verzeichnis ./nginx/certs gelegt.

Da wir unser Docker Registry in einem Container ausführen, können wir NGINX ebenfalls in einem Container ausführen, indem wir den folgenden Dienst zum compose.yaml Datei hinzufügen:

services:
  registry:
    # ...
  nginx:
    image: nginx:latest
    depends_on:
      - registry
    volumes:
      # mount the nginx configuration
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      # mount the certificates obtained from Let's Encrypt
      - ./nginx/certs:/etc/nginx/certs
    ports:
      - "443:443"

Unser nginx.conf Datei könnte wie folgt aussehen:

worker_processes auto;

events {
    worker_connections 1024;
}

http {
    upstream registry {
        server registry:5000;
    }

    server {
        server_name registry.pliutau.com;
        listen 443 ssl;

        ssl_certificate /etc/nginx/certs/fullchain.pem;
        ssl_certificate_key /etc/nginx/certs/privkey.pem;

        location / {
            # important setting for large images
            client_max_body_size                1000m;

            proxy_pass                          http://registry;
            proxy_set_header  Host              $http_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;
            proxy_read_timeout                  900;
        }
    }
}

Fertig zu gehen!

Nach diesen Schritten können wir unser Registery und den Nginx-Container ausführen.

docker-compose up

Nun kann man auf der Client-Seite die Images von Ihrem Registery push und pull machen. Aber zuerst müssen wir sich beim Registery anmelden.

docker login registry.pliutau.com

# Username: busy
# Password: bee
# Login Succeeded

Es ist Zeit, unseres Bilder zu bauen und in unser selbstgehostetes Registery zu pushen:

docker build -t registry.pliutau.com/pliutau/hello-world:v0 .

docker push registry.pliutau.com/pliutau/hello-world:v0
# v0: digest: sha256:a56ea4... size: 738

Auf Ihrem Server können Sie die hochgeladenen Images im Datenordner überprüfen:

ls -la ./registry/data/docker/registry/v2/repositories/

Weitere Optionen

Wie im obigen Beispiel können Sie auch das Registery auf Kubernetes ausführen. Oder Sie könnten ein verwaltetes Registery-Dienst wie Harbor verwenden, der ein quelloffenes Registery ist, das avancierte Sicherheitfeature bietet und mit Docker und Kubernetes kompatibel ist.

Daher könnten Sie auch eine Benutzeroberfläche für Ihren selbstgehosteten Registry-Dienst verwenden, indem Sie ein Projekt wie joxit/docker-registry-ui nutzen und es in einem separaten Container ausführen.

Fazit

Selbstgehostete Container-Registries ermöglichen Ihnen, die volle Kontrolle über Ihre Registry und ihre Deployment-Art zu haben. Gleichzeitig enthält dies jedoch die Kosten für die Wartung und die Sicherung der Registry.

Egal, was Ihre Gründe für den Betrieb einer selbstgehosteten Registry sind, Sie kennen nun, wie es geht. Von hier können Sie die verschiedenen Optionen vergleichen und diejenige wählen, die am besten zu Ihren Bedürfnissen passt.

Der vollständige Quellcode für diese Demo finden Sie auf GitHub. Außerdem können Sie ihn als Video auf unserem YouTube-Kanal anschauen.