Comment configurer un registre Docker privé sur Rocky Linux 8

Si tu travailles pour une organisation et que tu veux garder tes images docker en interne pour un déploiement rapide, l’hébergement d’un dépôt Docker privé est parfait. Avoir un registre docker privé te permet de posséder ton pipeline de distribution d’images et d’avoir un contrôle plus strict sur le stockage et la distribution des images. Tu peux intégrer ton registre à ton système CI/CD en améliorant ton flux de travail.

Ce tutoriel t’apprendra à configurer et à utiliser un registre Docker privé sur un serveur basé sur Rocky Linux 8 en utilisant Amazon S3 comme emplacement de stockage.

Conditions préalables

  • Deux serveurs Linux avec Rocky Linux 8. Un serveur fera office d’hôte du registre, tandis que l’autre sera utilisé comme client pour envoyer des demandes et recevoir des images de l’hôte.
  • Un nom de domaine enregistré pointant vers le serveur hôte. Nous utiliserons registry.example.com pour notre tutoriel.
  • Un utilisateur non-root avec des privilèges sudo sur les deux machines.

Étape 1 – Configurer le pare-feu

La première étape consiste à configurer le pare-feu. Rocky Linux utilise le pare-feu Firewalld. Vérifie l’état du pare-feu.

$ sudo firewall-cmd --state
running

Le pare-feu fonctionne avec différentes zones, et la zone publique est celle que nous utiliserons par défaut. Fais la liste de tous les services et ports actifs sur le pare-feu.

$ sudo firewall-cmd --permanent --list-services

Il devrait afficher la sortie suivante.

cockpit dhcpv6-client ssh

Autorise les ports HTTP et HTTPS.

$ sudo firewall-cmd --permanent --add-service=http
$ sudo firewall-cmd --permanent --add-service=https

Vérifie à nouveau l’état du pare-feu.

$ sudo firewall-cmd --permanent --list-services

Tu devrais voir une sortie similaire.

cockpit dhcpv6-client http https ssh

Recharge le pare-feu pour activer les modifications.

$ sudo firewall-cmd --reload

Étape 2 – Installe Docker et Docker Compose

Cette étape est requise à la fois sur le serveur et sur les machines clientes.

Installe le dépôt officiel de Docker.

$ sudo dnf install yum-utils
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

Installe Docker.

$ sudo dnf install docker-ce docker-ce-cli containerd.io

Active et exécute le démon Docker.

$ sudo systemctl enable docker --now

Ajoute ton utilisateur système au groupe Docker pour éviter d’utiliser sudo pour exécuter les commandes Docker.

$ sudo usermod -aG docker $(whoami)

Connecte-toi à nouveau à ton serveur après t’être déconnecté pour activer le changement.

Télécharge et installe la dernière version stable de Docker Compose.

$ 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

Applique les autorisations d’exécution au fichier binaire téléchargé.

$ sudo chmod +x /usr/local/bin/docker-compose

Installe le script de complétion Bash de Docker-compose.

$ sudo curl \
    -L https://raw.githubusercontent.com/docker/compose/1.29.2/contrib/completion/bash/docker-compose \
    -o /etc/bash_completion.d/docker-compose

Recharge les paramètres de ton profil pour que la complétion bash fonctionne.

$ source ~/.bashrc

Étape 3 – Configurer le registre Docker

Crée des répertoires d’utilisateurs

Crée un répertoire pour la configuration du registre.

$ mkdir ~/docker-registry

Passe dans le répertoire docker-registry.

$ cd ~/docker-registry

Crée un répertoire pour stocker le mot de passe d’authentification HTTP, les fichiers de configuration Nginx et les certificats SSL.

$ mkdir auth

Crée un autre répertoire pour stocker les journaux de Nginx.

$ mkdir logs

Créer un seau Amazon S3

Tu peux stocker les données du registre et les images sur ton serveur ou utiliser un service d’hébergement en nuage. Pour notre tutoriel, nous utiliserons le service de cloud Amazon S3.

L’étape suivante consiste à définir le fichier de configuration avec quelques paramètres importants. Ces paramètres peuvent aussi être définis dans le fichier docker-compose.yml, mais avoir un fichier séparé est bien mieux.

Crée un seau avec les paramètres suivants.

  • L’ACL doit être désactivé.
  • L’accès public au seau doit être désactivé.
  • Le versioning du seau doit être désactivé.
  • Active le cryptage du seau en utilisant les clés gérées par Amazon S3. (SSE-S3)
  • Le verrouillage des objets doit être désactivé.

Crée un utilisateur IAM avec la politique suivante.

{
  "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/*"
    }
  ]
}

Remplace l’adresse S3_BUCKET_NAME par le nom de ton seau S3.

Note la clé secrète, la valeur secrète et la région de ton seau qui seront utilisées plus tard.

Crée le fichier Docker Compose

Crée le fichier docker-compose.yml et ouvre-le pour le modifier.

$ nano docker-compose.yml

Colle le code suivant dans ce fichier.

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

Enregistre le fichier en appuyant sur Ctrl + X et en saisissant Y lorsque tu y es invité.

Passons en revue ce que nous avons mis en place dans notre fichier compose.

  1. La première étape consiste à récupérer la dernière image de la version 2 du registre Docker depuis le hub. Nous n’utilisons pas la dernière balise car elle peut poser des problèmes en cas de mise à jour majeure de la version. Le paramétrer sur 2 te permet de saisir toutes les mises à jour 2.x tout en évitant d’être mis à niveau automatiquement vers la prochaine version majeure, ce qui peut introduire des changements cassants.

  2. Le conteneur de registre est configuré pour redémarrer toujours en cas de panne ou d’arrêt inattendu.

  3. Nous avons défini diverses variables d’environnement pour le stockage Amazon S3. Passons-les en revue rapidement.

    • REGISTRY_STORAGE définit le type de stockage. Nous avons choisi s3 puisque nous utilisons Amazon S3.
    • REGISTRY_STORAGE_S3_REGION définit la région de ton seau S3.
    • REGISTRY_STORAGE_S3_BUCKET définit le nom de ton seau S3.
    • REGISTRY_STORAGE_S3_ENCRYPT– donne la valeur true si tu as activé le cryptage du seau.
    • REGISTRY_STORAGE_S3_CHUNKSIZE définit la taille des chunks de téléchargement. Elle doit être supérieure à 5MB (5 * 1024 * 1024).
    • REGISTRY_STORAGE_S3_SECURE– mets-le sur true si tu vas utiliser HTTPS.
    • REGISTRY_STORAGE_S3_ACCESSKEY et REGISTRY_STORAGE_S3_SECRETKEY – Les informations d’identification de l’utilisateur que tu as récupérées après avoir créé ton utilisateur IAM.
    • REGISTRY_STORAGE_S3_V4AUTH – mets-le sur true si tu utilises la v4 de l’authentification AWS. Si tu obtiens des erreurs liées à la connexion S3, mets-le sur false.
    • REGISTRY_STORAGE_S3_ROOTDIRECTORY – définit le répertoire racine de ton seau sous lequel tes données de registre seront stockées.
    • REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR – définit l’emplacement du cache. Dans notre cas, nous le stockons en mémoire. Tu peux aussi le définir pour utiliser Redis.
    • REGISTRY_HEALTH_STORAGEDRIVER_ENABLED – Donne la valeur false pour désactiver le service de contrôle de la santé du stockage du Registre. Il y a un bug avec le Registre qui peut causer des problèmes si tu ne le mets pas à false.
  4. Le registre de Docker communique via le port 5000, qui est celui que nous avons exposé dans notre serveur à Docker.

  5. ./auth:/etc/nginx/conf.d Le mappage garantit que tous les paramètres de Nginx sont disponibles dans le conteneur.

  6. ./auth/nginx.conf:/etc/nginx/nginx.conf:ro met en correspondance le fichier de paramètres Nginx du système avec celui du conteneur en mode lecture seule.

  7. ./logs:/var/log/nginx permet d’accéder aux journaux de Nginx sur le système en établissant une correspondance avec le répertoire des journaux de Nginx dans le conteneur.

  8. Les paramètres du registre Docker sont stockés dans le fichier /etc/docker/registry/config.yml dans le conteneur, et nous l’avons mappé vers le fichier config.yml dans le répertoire actuel, que nous allons créer à l’étape suivante.

Configurer l’authentification

Pour configurer l’authentification HTTP, tu dois installer le paquet httpd-tools.

$ sudo dnf install httpd-tools

Crée le fichier de mot de passe dans le répertoire ~/docker-registry/auth.

$ htpasswd -Bc ~/docker-registry/auth/nginx.htpasswd user1
New password:
Re-type new password:
Adding password for user user1

Le drapeau -c indique à la commande de créer un nouveau fichier, et le drapeau -B permet d’utiliser l’algorithme bcrypt pris en charge par Docker. Remplace user1 par un nom d’utilisateur de ton choix.

Si tu veux ajouter d’autres utilisateurs, exécute à nouveau la commande, mais sans le drapeau -c.

$ htpasswd -B ~/docker-registry/auth/registry.password user2

Maintenant, le fichier sera mappé au conteneur de registre pour l’authentification.

Étape 4 – Installer SSL

Pour installer un certificat SSL à l’aide de Let’s Encrypt, nous devons télécharger l’outil Certbot, qui est disponible dans le référentiel Epel.

Installe le dépôt EPEL et Certbot.

$ sudo dnf install epel-release 
$ sudo dnf install certbot

Génère un certificat SSL.

$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d registry.example.com

La commande ci-dessus téléchargera un certificat dans le répertoire /etc/letsencrypt/live/registry.example.com sur ton serveur.

Génère un certificat de groupe Diffie-Hellman.

$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

Teste le renouvellement du certificat.

$ sudo certbot renew --dry-run

Si le test à sec réussit, cela signifie que tes certificats seront automatiquement renouvelés.

Copie le fichier Dhparam dans le conteneur

Copie le certificat du groupe Diffie-Hellman dans le répertoire ~/docker-registry/auth, qui sera mappé au conteneur.

$ sudo cp /etc/ssl/certs/dhparam.pem ~/docker-registry/auth

Étape 5 – Configurer Nginx

L’étape suivante consiste à configurer le serveur Nginx en tant que proxy frontal pour le serveur du registre Docker. Le registre Docker est livré avec un serveur intégré fonctionnant sur le port 5000. Nous allons le placer derrière Nginx.

Crée et ouvre le fichier ~/docker-registry/auth/nginx.conf pour le modifier.

$ sudo nano ~/docker-registry/auth/nginx.conf

Colle le code suivant dans ce fichier.

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;
    }
  }
}

Enregistre le fichier en appuyant sur Ctrl + X et en saisissant Y lorsque tu y es invité une fois terminé.

Configure SELinux pour autoriser les connexions réseau pour le Private Docker Registry.

$ sudo setsebool -P httpd_can_network_connect on

Étape 6 – Lance Docker Registry

Passe dans le répertoire du registre Docker.

$ cd ~/docker-registry

Lance le conteneur Docker.

$ docker-compose up -d

Vérifie l’état des conteneurs.

$ 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

Connecte-toi au registre Docker.

$ docker login -u=testuser -p=testpassword https://registry.example.com

Tu peux aussi ouvrir l’URL https://registry.example.com/v2/ dans ton navigateur, et il te demandera un nom d’utilisateur et un mot de passe. Tu devrais voir une page vide avec {} dessus.

Tu peux vérifier l’URL sur le terminal en utilisant curl.

$ curl -u testuser -X GET https://registry.nspeaks.xyz/v2/
Enter host password for user 'testuser':
{}

Télécharge la dernière image docker Ubuntu.

$ docker pull ubuntu:latest

Marque cette image pour le registre privé.

$ docker tag ubuntu:latest registry.example.com/ubuntu2004

Pousse l’image vers le registre.

$ docker push registry.example.com/ubuntu2004

Vérifie si le push a réussi.

$ curl -u testuser -X GET https://registry.nspeaks.xyz/v2/_catalog
Enter host password for user 'testuser':
{"repositories":["ubuntu2004"]}

Saisis ton mot de passe d’authentification Nginx lorsque tu y es invité, et tu verras la liste des référentiels disponibles via le registre.

Vérifie la liste des images Docker actuellement disponibles pour être utilisées.

$ 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

Étape 7 – Accéder et utiliser le registre Docker depuis la machine cliente

Connecte-toi à ton client-serveur. À l’étape 1, nous avons installé Docker sur la machine cliente.

Connecte-toi au registre privé de Docker depuis la machine cliente.

$ docker login -u=testuser -p=testpassword https://registry.example.com

Tire l’image Ubuntu du registre.

$ docker pull registry.example.com/ubuntu2004

Répertorie toutes les images sur ta machine cliente.

$ docker images
REPOSITORY                        TAG        IMAGE ID       CREATED         SIZE
registry.nspeaks.xyz/ubuntu2004   latest     ff0fea8310f3   2 weeks ago     72.8MB

Crée et lance un conteneur en utilisant l’image téléchargée.

$ docker run -it registry.example.com/ubuntu2004 /bin/bash

Tu seras connecté au Shell à l’intérieur du conteneur Ubuntu.

root@a2da49fdbea9:

Exécute la commande suivante pour vérifier la version de Linux.

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

Maintenant, tu peux commencer à utiliser ton registre Docker depuis tes machines clientes.

Conclusion

Ceci conclut notre tutoriel sur la configuration d’un registre Docker privé sur un serveur basé sur Rocky Linux 8 qui utilise Amazon S3 comme stockage. Si tu as des questions, poste-les dans les commentaires ci-dessous.

Vous aimerez aussi...