So richtest du eine private Docker-Registry auf Rocky Linux 8 ein
Wenn du für ein Unternehmen arbeitest und deine Docker-Images für eine schnelle Bereitstellung intern aufbewahren möchtest, dann ist das Hosting eines privaten Docker-Repositorys perfekt. Mit einer privaten Docker-Registry hast du die Kontrolle über die Verteilungspipeline deiner Images und kannst die Speicherung und Verteilung der Images besser kontrollieren. Du kannst deine Registry in dein CI/CD-System integrieren und so deinen Workflow verbessern.
In diesem Tutorial erfährst du, wie du eine private Docker-Registry auf einem Rocky Linux 8 basierten Server einrichtest und verwendest, der Amazon S3 als Speicherort nutzt.
Voraussetzungen
- Zwei Linux-Server mit Rocky Linux 8. Ein Server dient als Registry-Host, während der andere als Client verwendet wird, um Anfragen zu senden und Images vom Host zu empfangen.
- Ein registrierter Domänenname, der auf den Hostserver zeigt. Für unseren Lehrgang werden wir
registry.example.com
verwenden. - Ein Nicht-Root-Benutzer mit sudo-Rechten auf beiden Rechnern.
Schritt 1 – Firewall konfigurieren
Der erste Schritt besteht darin, die Firewall zu konfigurieren. Rocky Linux verwendet die Firewalld Firewall. Überprüfe den Status der Firewall.
$ sudo firewall-cmd --state running
Die Firewall arbeitet mit verschiedenen Zonen, wobei die öffentliche Zone die Standardzone ist, die wir verwenden werden. Liste alle Dienste und Ports auf, die auf der Firewall aktiv sind.
$ sudo firewall-cmd --permanent --list-services
Es sollte die folgende Ausgabe angezeigt werden.
cockpit dhcpv6-client ssh
Lasse HTTP- und HTTPS-Ports zu.
$ sudo firewall-cmd --permanent --add-service=http $ sudo firewall-cmd --permanent --add-service=https
Überprüfe erneut den Status der Firewall.
$ sudo firewall-cmd --permanent --list-services
Du solltest eine ähnliche Ausgabe sehen.
cockpit dhcpv6-client http https ssh
Lade die Firewall neu, um die Änderungen zu aktivieren.
$ sudo firewall-cmd --reload
Schritt 2 – Installiere Docker und Docker Compose
Dieser Schritt ist sowohl auf dem Server als auch auf den Client-Rechnern erforderlich.
Installiere das offizielle Docker-Repository.
$ sudo dnf install yum-utils $ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
Installiere Docker.
$ sudo dnf install docker-ce docker-ce-cli containerd.io
Aktiviere den Docker-Daemon und starte ihn.
$ sudo systemctl enable docker --now
Füge deinen Systembenutzer zur Docker-Gruppe hinzu, um zu vermeiden, dass du sudo
zur Ausführung von Docker-Befehlen verwendest.
$ sudo usermod -aG docker $(whoami)
Melde dich nach dem Abmelden erneut bei deinem Server an, um die Änderung zu aktivieren.
Lade die neueste stabile Version von Docker Compose mit curl herunter und installiere sie.
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Gib der heruntergeladenen Binärdatei die Berechtigung zum Ausführen.
$ sudo chmod +x /usr/local/bin/docker-compose
Installiere das Docker-compose Bash Completion Skript.
$ sudo curl \ -L https://raw.githubusercontent.com/docker/compose/1.29.2/contrib/completion/bash/docker-compose \ -o /etc/bash_completion.d/docker-compose
Lade deine Profileinstellungen neu, damit die Bash-Vervollständigung funktioniert.
$ source ~/.bashrc
Schritt 3 – Docker Registry konfigurieren
Benutzerverzeichnisse erstellen
Erstelle ein Verzeichnis für die Konfiguration der Registry.
$ mkdir ~/docker-registry
Wechsle in das Verzeichnis docker-registry
.
$ cd ~/docker-registry
Erstelle ein Verzeichnis, in dem das Passwort für die HTTP-Authentifizierung, die Nginx-Konfigurationsdateien und die SSL-Zertifikate gespeichert werden.
$ mkdir auth
Erstelle ein weiteres Verzeichnis, um Nginx-Protokolle zu speichern.
$ mkdir logs
Amazon S3 Bucket erstellen
Du kannst die Registrierungsdaten und die Bilder auf deinem Server speichern oder einen Cloud-Hosting-Dienst nutzen. Für unser Tutorial werden wir den Amazon S3 Cloud Service verwenden.
Der nächste Schritt besteht darin, die Konfigurationsdatei mit einigen wichtigen Einstellungen einzurichten. Diese Einstellungen können auch in der Datei docker-compose.yml
festgelegt werden, aber eine separate Datei ist viel besser.
Erstelle einen Bucket mit den folgenden Einstellungen.
- ACL sollte deaktiviert sein.
- Der öffentliche Zugriff auf den Bucket sollte deaktiviert sein.
- Die Bucket-Versionierung sollte deaktiviert sein.
- Aktiviere die Bucket-Verschlüsselung mit den von Amazon S3 verwalteten Schlüsseln. (SSE-S3)
- Die Objektsperre sollte deaktiviert sein.
Erstelle einen IAM-Benutzer mit der folgenden Richtlinie.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetBucketLocation", "s3:ListBucketMultipartUploads" ], "Resource": "arn:aws:s3:::S3_BUCKET_NAME" }, { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:ListMultipartUploadParts", "s3:AbortMultipartUpload" ], "Resource": "arn:aws:s3:::S3_BUCKET_NAME/*" } ] }
Ersetze S3_BUCKET_NAME
durch den Namen deines S3-Buckets.
Notiere dir den geheimen Schlüssel, den geheimen Wert und die Bucket-Region deines Buckets, die später verwendet werden sollen.
Docker Compose-Datei erstellen
Erstelle die Datei docker-compose.yml
und öffne sie zur Bearbeitung.
$ nano docker-compose.yml
Füge den folgenden Code in die Datei ein.
version: '3.3' services: registry: image: registry:2 restart: always environment: - REGISTRY_STORAGE=s3 - REGISTRY_STORAGE_S3_REGION=us-west-2 - REGISTRY_STORAGE_S3_BUCKET=hf-docker-registry - REGISTRY_STORAGE_S3_ENCRYPT=true - REGISTRY_STORAGE_S3_CHUNKSIZE=5242880 - REGISTRY_STORAGE_S3_SECURE=true - REGISTRY_STORAGE_S3_ACCESSKEY=AKIA3FIG4NVFCJ6STMUA - REGISTRY_STORAGE_S3_SECRETKEY=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 - REGISTRY_STORAGE_S3_V4AUTH=true - REGISTRY_STORAGE_S3_ROOTDIRECTORY=/image-registry - REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR=inmemory - REGISTRY_HEALTH_STORAGEDRIVER_ENABLED=false nginx: image: "nginx:alpine" ports: - 443:443 links: - registry:registry volumes: - ./auth:/etc/nginx/conf.d - ./auth/nginx.conf:/etc/nginx/nginx.conf:ro - ./logs:/var/log/nginx - /etc/letsencrypt:/etc/letsencrypt
Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.
Gehen wir nun durch, was wir in unserer Compose-Datei eingerichtet haben.
- Der erste Schritt besteht darin, das neueste Image der Version 2 der Docker-Registry aus dem Hub zu holen. Wir verwenden nicht das neueste Tag, weil es bei einem größeren Versions-Upgrade zu Problemen führen kann. Mit dem Tag 2 kannst du alle 2.x-Updates abrufen und gleichzeitig verhindern, dass ein automatisches Upgrade auf die nächste Hauptversion durchgeführt wird, was zu fehlerhaften Änderungen führen kann.
- Der Registrierungscontainer ist so eingestellt, dass er im Falle eines Fehlers oder eines unerwarteten Herunterfahrens immer neu startet.
- Wir haben verschiedene Umgebungsvariablen für den Amazon S3-Speicher gesetzt. Gehen wir sie kurz durch.
- REGISTRY_STORAGE legt die Art des Speichers fest. Wir haben s3 gewählt, da wir Amazon S3 verwenden.
- REGISTRY_STORAGE_S3_REGION legt die Region deines S3-Buckets fest.
- REGISTRY_STORAGE_S3_BUCKET legt den Namen deines S3-Buckets fest.
- REGISTRY_STORAGE_S3_ENCRYPT– setzt es auf true, wenn du die Bucket-Verschlüsselung aktiviert hast.
- REGISTRY_STORAGE_S3_CHUNKSIZE legt die Größe der Upload-Chunks fest. Sie sollte größer als 5MB (5 * 1024 * 1024) sein.
- REGISTRY_STORAGE_S3_SECURE– setze ihn auf true, wenn du HTTPS verwenden willst.
- REGISTRY_STORAGE_S3_ACCESSKEY und REGISTRY_STORAGE_S3_SECRETKEY – Benutzeranmeldedaten, die du nach der Erstellung deines IAM-Benutzers erhalten hast.
- REGISTRY_STORAGE_S3_V4AUTH – Setze es auf true, wenn du v4 der AWS-Authentifizierung verwendest. Wenn du Fehler bei der S3-Anmeldung bekommst, setze ihn auf false.
- REGISTRY_STORAGE_S3_ROOTDIRECTORY – legt das Stammverzeichnis in deinem Bucket fest, in dem deine Registrierungsdaten gespeichert werden.
- REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR – legt den Speicherort für den Cache fest. In unserem Fall speichern wir ihn im Speicher. Du kannst auch festlegen, dass Redis verwendet wird.
- REGISTRY_HEALTH_STORAGEDRIVER_ENABLED – Setze diesen Wert auf false, um den Storage Health Check Service der Registry zu deaktivieren. Es gibt einen Fehler in der Registry, der zu Problemen führen kann, wenn du diesen Wert nicht auf false setzt.
- Die Docker Registry kommuniziert über Port 5000, den wir in unserem Server für Docker freigegeben haben.
./auth:/etc/nginx/conf.d
mapping stellt sicher, dass alle Einstellungen von Nginx im Container verfügbar sind../auth/nginx.conf:/etc/nginx/nginx.conf:ro
mappt die Nginx-Einstellungsdatei vom System auf eine Datei im Container im schreibgeschützten Modus../logs:/var/log/nginx
ermöglicht den Zugriff auf die Nginx-Logs auf dem System, indem sie auf das Nginx-Logs-Verzeichnis im Container abgebildet wird.- Die Einstellungen der Docker-Registry werden in der Datei
/etc/docker/registry/config.yml
im Container gespeichert, und wir haben sie auf die Dateiconfig.yml
im aktuellen Verzeichnis abgebildet, die wir im nächsten Schritt erstellen werden.
Authentifizierung einrichten
Um die HTTP-Authentifizierung einzurichten, musst du das Paket httpd-tools
installieren.
$ sudo dnf install httpd-tools
Erstelle die Passwortdatei im Verzeichnis ~/docker-registry/auth
.
$ htpasswd -Bc ~/docker-registry/auth/nginx.htpasswd user1 New password: Re-type new password: Adding password for user user1
Das Flag -c
weist den Befehl an, eine neue Datei zu erstellen, und das Flag -B
sorgt dafür, dass der von Docker unterstützte bcrypt-Algorithmus verwendet wird. Ersetze user1
durch einen Benutzernamen deiner Wahl.
Wenn du weitere Benutzer hinzufügen möchtest, führe den Befehl erneut aus, aber ohne das -c
Flag.
$ htpasswd -B ~/docker-registry/auth/registry.password user2
Jetzt wird die Datei zur Authentifizierung auf den Registrierungscontainer abgebildet.
Schritt 4 – SSL installieren
Um ein SSL-Zertifikat mit Let’s Encrypt zu installieren, müssen wir das Tool Certbot herunterladen, das im Epel-Repository verfügbar ist.
Installiere das EPEL-Repository und Certbot.
$ sudo dnf install epel-release $ sudo dnf install certbot
Erstelle ein SSL-Zertifikat.
$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m name@example.com -d registry.example.com
Mit dem obigen Befehl wird ein Zertifikat in das Verzeichnis /etc/letsencrypt/live/registry.example.com
auf deinem Server heruntergeladen.
Erstelle ein Diffie-Hellman-Gruppenzertifikat.
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
Teste die Erneuerung des Zertifikats.
$ sudo certbot renew --dry-run
Wenn der Probelauf erfolgreich ist, bedeutet das, dass deine Zertifikate automatisch erneuert werden.
Kopiere die Dhparam-Datei in den Container
Kopiere das Diffie-Hellman-Gruppenzertifikat in das Verzeichnis ~/docker-registry/auth
, das auf den Container abgebildet werden soll.
$ sudo cp /etc/ssl/certs/dhparam.pem ~/docker-registry/auth
Schritt 5 – Nginx konfigurieren
Der nächste Schritt besteht darin, den Nginx-Server als Front-End-Proxy für den Docker-Registry-Server zu konfigurieren. Docker Registry verfügt über einen eingebauten Server, der auf Port 5000 läuft. Wir werden ihn hinter Nginx platzieren.
Erstelle und öffne die Datei ~/docker-registry/auth/nginx.conf
zum Bearbeiten.
$ sudo nano ~/docker-registry/auth/nginx.conf
Füge den folgenden Code in die Datei ein.
events { worker_connections 1024; } http { upstream docker-registry { server registry:5000; } ## Set a variable to help us decide if we need to add the ## 'Docker-Distribution-Api-Version' header. ## The registry always sets this header. ## In the case of nginx performing auth, the header is unset ## since nginx is auth-ing before proxying. map $upstream_http_docker_distribution_api_version $docker_distribution_api_version { '' 'registry/2.0'; } server { listen 443 ssl http2; server_name registry.example.com; # SSL ssl_certificate /etc/letsencrypt/live/registry.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/registry.example.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/registry.example.com/chain.pem; access_log /var/log/nginx/registry.access.log; error_log /var/log/nginx/registry.error.log; # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers on; ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1; ssl_session_cache shared:SSL:10m; ssl_dhparam /etc/nginx.d/conf.d/dhparam.pem; resolver 8.8.8.8; # disable any limits to avoid HTTP 413 for large image uploads client_max_body_size 0; # required to avoid HTTP 411: see Issue #1486 (https://github.com/moby/moby/issues/1486) chunked_transfer_encoding on; location /v2/ { # Do not allow connections from docker 1.5 and earlier # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) { return 404; } # To add basic authentication to v2 use auth_basic setting. auth_basic "Registry realm"; auth_basic_user_file /etc/nginx/conf.d/nginx.htpasswd; ## If $docker_distribution_api_version is empty, the header is not added. ## See the map directive above where this variable is defined. add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always; proxy_pass http://docker-registry; proxy_set_header Host $http_host; # required for docker client's sake proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 900; } } }
Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.
Konfiguriere SELinux, um Netzwerkverbindungen für die Private Docker Registry zuzulassen.
$ sudo setsebool -P httpd_can_network_connect on
Schritt 6 – Docker Registry starten
Wechsle in das Verzeichnis der Docker Registry.
$ cd ~/docker-registry
Starte den Docker-Container.
$ docker-compose up -d
Überprüfe den Status der Container.
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 88d6addc1687 nginx:alpine "/docker-entrypoint.…" 5 minutes ago Up 5 minutes 80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp docker-registry_nginx_1 2b112edc1c72 registry:2 "/entrypoint.sh /etc…" 5 minutes ago Up 5 minutes 5000/tcp docker-registry_registry_1
Melde dich bei der Docker Registry an.
$ docker login -u=testuser -p=testpassword https://registry.example.com
Du kannst auch die URL https://registry.example.com/v2/
in deinem Browser öffnen und wirst nach einem Benutzernamen und Passwort gefragt. Du solltest eine leere Seite mit {} darauf sehen.
Du kannst die URL im Terminal mit curl
überprüfen.
$ curl -u testuser -X GET https://registry.nspeaks.xyz/v2/ Enter host password for user 'testuser': {}
Lade das neueste Ubuntu-Docker-Image herunter.
$ docker pull ubuntu:latest
Markiere dieses Image für die private Registry.
$ docker tag ubuntu:latest registry.example.com/ubuntu2004
Pushe das Image in die Registry.
$ docker push registry.example.com/ubuntu2004
Teste, ob der Push erfolgreich war.
$ curl -u testuser -X GET https://registry.nspeaks.xyz/v2/_catalog Enter host password for user 'testuser': {"repositories":["ubuntu2004"]}
Gib dein Nginx-Authentifizierungspasswort ein, wenn du dazu aufgefordert wirst, und du siehst die Liste der über die Registry verfügbaren Repositories.
Überprüfe die Liste der Docker-Images, die derzeit zur Nutzung zur Verfügung stehen.
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE registry 2 d3241e050fc9 5 days ago 24.2MB nginx alpine 53722defe627 5 days ago 23.4MB httpd 2 118b6abfbf55 5 days ago 144MB ubuntu latest ff0fea8310f3 2 weeks ago 72.8MB registry.nspeaks.xyz/ubuntu2004 latest ff0fea8310f3 2 weeks ago 72.8MB
Schritt 7 – Zugriff und Nutzung der Docker-Registry vom Client-Rechner aus
Melde dich bei deinem Client-Server an. In Schritt 1 haben wir Docker auf dem Client-Rechner installiert.
Melde dich vom Client-Rechner aus bei der privaten Docker-Registry an.
$ docker login -u=testuser -p=testpassword https://registry.example.com
Ziehe das Ubuntu-Image aus der Registry.
$ docker pull registry.example.com/ubuntu2004
Liste alle Images auf deinem Client-Rechner auf.
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE registry.nspeaks.xyz/ubuntu2004 latest ff0fea8310f3 2 weeks ago 72.8MB
Erstelle und starte einen Container mit dem heruntergeladenen Image.
$ docker run -it registry.example.com/ubuntu2004 /bin/bash
Du wirst in der Shell innerhalb des Ubuntu-Containers angemeldet sein.
root@a2da49fdbea9:
Führe den folgenden Befehl aus, um die Linux-Version zu überprüfen.
root@a2da49fdbea9$ cat /etc/os-release NAME="Ubuntu" VERSION="20.04.4 LTS (Focal Fossa)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.04.4 LTS" VERSION_ID="20.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=focal UBUNTU_CODENAME=focal
Jetzt kannst du deine Docker-Registry von deinen Client-Rechnern aus nutzen.
Fazit
Damit ist unsere Anleitung zum Einrichten einer privaten Docker-Registry auf einem Rocky Linux 8 basierten Server, der Amazon S3 als Speicherplatz nutzt, abgeschlossen. Wenn du noch Fragen hast, schreibe sie in die Kommentare unten.