Docker permet d’utiliser gratuitement son Docker Hub avec 1 registre Docker (Docker Registry en 🇬🇧) mais nous avons également la possibilité d’auto-héberger des registres Docker sur notre propre infrastructure.

On peut vouloir héberger un registre Docker sur ses serveurs pour divers raisons comme pour par exemple « maîtriser » l’accès à ses images docker, les rendre disponible sur le réseau local (qui peut être isolé d’internet), pour des raisons de performances (notamment avec une CI locale) ou juste pour comprendre 🤓 comment fonctionne l’écosystème Docker.

Ce poste est basé de la doc officielle et la page concernant les certificats auto-générés/signés.

Vue d’ensemble

registre docker local

Installation

Coté serveur

Le registre docker que nous allons utiliser est simplement une instance d’une image officielle registry:2, il va donc falloir avoir un environnement docker fonctionnel installé sur le serveur et une pair clé SSL/certificat car la connexion au registre docker doit être sécurisée (requis par défaut).

Génération de la clé et certificat par OpenSsl

D’abord se placer dans le dossier dans lequel nous allons stocker la clé privée et le certificat signé (dossier certs), puis les générer:

openssl req -newkey rsa:4096 -nodes -sha256      \
     -keyout docker-registry.key -x509 -days 365 \
     -out docker-registry.crt

Configuration [optionnel]

Il est possible de configurer finement le Registre via un fichier config.yml monté dans un volume, mais c’est optionnel (sauf si vous visez une configuration de production):

docker run -d -p 443:443 --restart=always --name registry   \
        -v `pwd`/config.yml:/etc/docker/registry/config.yml \
        registry:2

Démarrer le registre local

Démarrer le conteneur docker basé sur l’image officielle registry:2 :

docker run -d --restart=always --name mon-registre -v "$(pwd)"/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/docker-registry.crt -e REGISTRY_HTTP_TLS_KEY=/certs/docker-registry.key -p 443:443 registry:2
# se placer dans le dossier contenant le dossier certs

Coté client

Copie du certificat serveur sur les clients Docker

Il faut uniquement installer le certificat (fichier docker-registry.crt) que nous avons précédemment généré coté serveur dans un dossier spécifique /etc/docker/certs.d/mon-serveur:443/docker-registry.crt de chaque client docker qui souhaite communiquer avec.

Envoi réception des images

Utiliser les commandes docker push/pull avec la syntaxe suivante [REGISTRY_HOST[:REGISTRY_PORT]/]REPOSITORY[:TAG] pour envoyer/recevoir vers son registre privé exemple :

docker pull mon-serveur:443/mon-image

Troubleshooting des erreurs docker

Si vous tentez de récupérer une image sur votre Registre Docker fraichement installé, vous risquez de rencontrer quelques erreurs dont certains liés aux certificats.

Vérifier la liaison réseau

Il peut être utile de vérifier depuis le client que le conteneur docker est bien lancé coté serveur et qu’il écoute bien sur le port spécifié (443 dans notre exemple):

nc -vz  mon-serveur 443
# le résultat devrait ressembler à cela:
# Connection to mon-serveur 443 port [tcp/https] succeeded!

Server gave HTTP response to HTTPS client

Error response from daemon: Get https://mon-serveur:443/v2/: http: server gave HTTP response to HTTPS client

Explication

Le serveur (le registre docker) a été lancé sans certificat spécifiés par les variables d’environnements REGISTRY_HTTP_TLS_CERTIFICATE et/ou REGISTRY_HTTP_TLS_KEY

Solution

Vérifier que vous avez bien les fichiers .cert et .key (avec le bon chemin lors du lancement de la commande docker run) et que vous avez bien renseigné les options -e comme spécifié ci-dessus (installation coté serveur).

Unknown authority: certificat manquant coté client

Error response from daemon: Get https://mon-serveur:443/v2/: x509: certificate signed by unknown authority

Explication

Ce message indique certificate signed by unknown authority, c’est à dire que votre client ne reconnait pas l’autorité qui a signé le certificat SSL recu de votre serveur.

Solution

copier votre certificat docker-registry.crt sur votre client dans le dossier /etc/docker/certs.d/mon-serveur:443/docker-registry.crt

x509: certificate is not valid

Error response from daemon: Get https://mon-serveur:443/v2/: x509: certificate is not valid for any names, but wanted to match                              mon-serveur

Explication

Ce message indique certificate is not valid … but wanted to match mon-serveur, c’est à dire que la connexion a bien été établie avec le registre docker privé, mais que le certificat renvoyé ne correspond pas nom de domaine (ici mon-serveur).

Solution

Régénérer le certificat et la clé coté serveur en renseignant correctement la question :

Common Name (e.g. server FQDN or YOUR name) []:mon-serveur