Un registre de conteneurs est un catalogue de stockage depuis lequel vous pouvez envoyer et récupérer des images de conteneurs.

Il existe de nombreux registres publics et privés disponibles pour les développeurs, tels que Docker Hub, Amazon ECR et Google Cloud Artifact Registry. Cependant, parfois, au lieu de comptabiliser sur un fournisseur externe, vous pourriez souhaiter héberger vos images vous-même. Cela vous donne plus de contrôle sur la configuration du registre et sur l’hébergement des images de conteneurs.

Cet article est un tutoriel pratique qui vous apprendra comment héberger vous-même un registre de conteneurs.

Table des matières

Vous tirerez le meilleur parti de cet article si vous connaissez déjà les outils tels que Docker et NGINX et possédez une idée générale de ce qu’est un conteneur.

Qu’est-ce qu’une image de conteneur ?

Avant de parler des registres de conteneurs, voyons d’abord ce que représente une image de conteneur. En bref, une image de conteneur est un paquet contenant toutes les informations nécessaires pour exécuter un conteneur, y compris les fichiers, les bibliothèques et les configurations. Elles sont composées de couches où chaque couche représente un ensemble de modifications du système de fichiers qui ajoutent, suppriment ou modifient des fichiers.

La méthode la plus commune pour créer une image de conteneur est d’utiliser un Dockerfile.

# 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

Ceci crée une image de conteneur qui est stockée sur votre machine locale. Mais que faire si vous voulez partager cette image avec d’autres ou l’utiliser sur une machine différente ? C’est là que les registres de conteneurs entrent en jeu.

Qu’est-ce qu’un Registre de Conteneurs ?

Un registre de conteneurs est un catalogue de stockage où vous pouvez envoyer (push) et retirer (pull) des images de conteneurs. Les images sont regroupées dans des référentiels, qui sont des collections d’images liées avec le même nom. Par exemple, sur le registre Docker Hub, nginx est le nom du référentiel contenant les différentes versions des images NGINX.

Certains registres sont publics, ce qui signifie que les images hébergées sur eux sont accessibles à tous sur Internet. Des registres publics tels que Docker Hub sont une bonne option pour héberger des projets open-source.

D’autre part, les registres privés offrent une manière de intégrer la sécurité et la confidentialité dans le stockage des images de conteneurs d’entreprise, soit hébergés dans le cloud ou sur site. Ces registres privés sont souvent dotés de fonctionnalités de sécurité avancées et de support technique.

Il existe une liste croissante de registres privés tels que Amazon ECR, GCP Artifact Registry, GitHub Container Registry, et Docker Hub offre également une fonctionnalité de référentiel privé.

Comme développeur, vous interagissez avec un registre de conteneurs lors de l’utilisation des commandes docker push et docker pull.

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

# En cas de Docker Hub, nous pourrions également sauter la partie du registre
docker push pliutau/hello-world:v0

Venez nous faire connaître l’anatomie d’une URL de l’image de conteneur :

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

Pourquoi vous pourriez souhaiter héberger vous-même un registre de conteneurs

Parfois, au lieu de compter sur un fournisseur comme AWS ou GCP, vous pourriez souhaiter héberger vos images vous-même. Cela permet de garder votre infrastructure interne et de dépendre moins de fournisseurs externes. Dans certains secteurs réglementés, c’est même une exigence.

Un registre hébergé automatiquement fonctionne sur vos propres serveurs, ce qui vous donne plus de contrôle sur la configuration du registre et l’hébergement des images de conteneurs. Parallèlement, cela implique le maintien et la sécurisation du registre.

Comment héberger vous-même un registre de conteneurs

Plusieurs solutions de registres de conteneurs open-source sont disponibles. La plus populaire est officiellement supportée par Docker, appelée registry, avec sa réalisation pour le stockage et la distribution des images et des artefacts de conteneurs. Cela signifie que vous pouvez exécuter votre propre registre dans un conteneur.

Voici les principales étapes pour exécuter un registre sur un serveur :

  • Installer Docker et Docker Compose sur le serveur.

  • Configurer et exécuter le conteneur registry.

  • Exécuter NGINX pour gérer le TLS et faire passer les requêtes vers le conteneur registry.

  • Configurer les certificats SSL et définir un domaine.

Étape 1 : Installer Docker et Docker Compose sur le serveur

Vous pouvez utiliser n’importe quel serveur compatible Docker. Par exemple, vous pouvez utiliser une Droplet DigitalOcean avec Ubuntu. Pour cette démonstration, je suis allé sur Google Cloud Compute pour créer une VM avec Ubuntu.

neofetch

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

Une fois dans notre VM, nous devrions installer Docker et Docker Compose. Docker Compose est facultatif, mais il permet de gérer plus facilement les applications multi-conteneurs.

# install docker engine and docker-compose
sudo snap install docker

# verify the installation
docker --version
docker-compose --version

Étape 2 : Configurer et exécuter le conteneur registry

Ensuite, nous devons configurer notre conteneur registry. Le fichier suivant compose.yaml créera un conteneur registry avec un volume pour stocker les images et un volume pour stocker le fichier de mot de passe.

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:
      # Monter le fichier de mot de passe
      - ./registry/registry.password:/auth/registry.password
      # Monter le répertoire des données
      - ./registry/data:/data
    ports:
      - 5000

Le fichier de mot de passe défini dans REGISTRY_AUTH_HTPASSWD_PATH est utilisé pour authentifier les utilisateurs lorsqu’ils font des push ou des pull d’images depuis le registre. Nous devrions créer un fichier de mot de passe en utilisant la commande htpasswd. Nous devrions également créer un dossier pour stocker les images.

mkdir -p ./registry/data

# Installer htpasswd
sudo apt install apache2-utils

# Créer un fichier de mot de passe. nom d'utilisateur : busy, mot de passe : bee
htpasswd -Bbn busy bee > ./registry/registry.password

Maintenant, nous pouvons démarrer le conteneur du registre. Si vous voyez ce message, c’est que tout fonctionne comme prévu :

docker-compose up

# Un exécution réussi devrait afficher quelque chose comme ceci :
# registry | level=info msg="listening on [::]:5000"

Étape 3 : Exécuter NGINX pour gérer le TLS

Comme mentionné précédemment, nous pouvons utiliser NGINX pour gérer le TLS et forwarder les requêtes vers le conteneur du registre.

Le Registre Docker nécessite un certificat SSL valide et de confiance pour fonctionner. Vous pouvez utiliser quelque chose comme Let’s Encrypt ou le récupérer manuellement. Assurez-vous d’avoir un nom de domaine pointant vers votre serveur (registry.pliutau.com dans mon cas). Pour cette démonstration, j’ai déjà obtenu les certificats en utilisant certbot et les ai mis dans le répertoire ./nginx/certs.

Puisque nous exécutons notre registre Docker dans un conteneur, nous pouvons également exécuter NGINX dans un conteneur en ajoutant le service suivant au fichier compose.yaml :

services:
  registry:
    # ...
  nginx:
    image: nginx:latest
    depends_on:
      - registry
    volumes:
      # monter la configuration nginx
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      # monter les certificats obtenus de Let's Encrypt
      - ./nginx/certs:/etc/nginx/certs
    ports:
      - "443:443"

Notre fichier nginx.conf pourrait ressembler à ceci :

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 / {
            # paramètre important pour les images de grande taille
            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;
        }
    }
}

Prêt à aller !

Apres ces étapes, nous pouvons lancer les conteneurs de registre et de NGINX.

docker-compose up

Maintenant, du côté client, vous pouvez push et pull les images à partir de votre registre. Mais avant, nous devons nous connecter au registre.

docker login registry.pliutau.com

# Nom d'utilisateur : busy
# Mot de passe : bee
# Connexion réussie

C’est le moment de construire et de push notre image vers notre registre auto-hébergé :

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

Sur votre serveur, vous pouvez vérifier les images téléchargées dans le dossier data :

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

Autres options

En suivant l’exemple ci-dessus, vous pouvez également exécuter le registre sur Kubernetes. Ou vous pouvez utiliser un service de registre géré comme Harbor, qui est un registre open-source offrant des fonctionnalités de sécurité avancées et compatible avec Docker et Kubernetes.

Également, si vous voulez avoir une interface utilisateur pour votre registre hébergé personnel, vous pourriez utiliser un projet comme joxit/docker-registry-ui et le démarrer dans un conteneur séparé.

Conclusion

Les registres de conteneurs hébergés personnels vous permettent d’avoir un contrôle complet sur votre registre et sur la manière dont il est déployé. En même temps, cela implique le maintien et la sécurisation du registre.

Quelles que soient vos raisons de faire fonctionner un registre hébergé personnel, vous savez maintenant comment le faire. À partir de là, vous pouvez comparer les différentes options et choisir celle qui convient le mieux à vos besoins.

Vous pouvez trouver le code source complet de cette démonstration sur GitHub. De plus, vous pouvez l’regarder en vidéo sur notre chaîne YouTube.