Docker : Déployer un registre local décentralisé (Debian/Ubuntu)

Docker : Déployer un registre local décentralisé (Debian/Ubuntu)

Bonjour à tous ! Aujourd’hui nous allons voir comment installer et configurer un registry docker local. Un registre Docker privé vous permet de partager vos images docker au sein de votre organisation ou pour un projet. Cela vous permet d’être indépendant de docker hub, et de pouvoir héberger autant d’images privées que vous souhaitez. (Par défaut docker hub, vous autorise seulement une image privée). Ceci est une démarche de souveraineté numérique.

Un registre Docker est donc un espace virtuelle où vous pouvez publier vos images avec la commande docker push <image>, et les exécuter avec la commande docker {pull,run} <image>

I. Installation de l’environnement

Positionnez-vous à la racine de votre serveur

cd /

Puis, créez un dossier /docker-registry et rentrez dans celui-ci.

mkdir docker-registry && cd docker-registry

A l’intérieur de ce dossier, nous allons créer deux répertoires à savoir certs/ et auth/ :

mkdir {certs,auth}

Le dossier auth va nous permettre de pouvoir gérer la partie authentification. Dirigez-vous dans celui-ci.

cd auth

Nous allons créer un utilisateur ainsi qu’un mot de passe qui lui sera associé. Ce couple d’identifiant, nous permet de sécuriser notre registre local. En effet comme vous vous en doutez, seules les personnes authentifiées doivent pouvoir publier, ou exécuter une image.

  • Username : dockerRegistryUser
  • password: password
docker run \
--entrypoint htpasswd \
httpd -Bbn dockerRegistryUser password > htpasswd

Note : L’algorithme de chiffrement utilisé ici est bcrypt, toujours considéré comme étant sécurisé en 2022.

Le hash de notre mot de passe se situe dans le fichier htpasswd

Pour le moment, nous en avont finit avec le dossier auth/. Passons maintenant au dossier certs/

cd ../certs

Afin de sécurisé l’accès à notre registry local, nous devons générer un certificat de chiffrement pour pouvoir accéder à notre registry via HTTPS :

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

Note : Vous pouvez utiliser letsencrypt, si vous disposez d’un nom de domaine et que vous souhaitez exposer votre registry sur internet (ce que je ne conseil pas personnellement)

Adaptez votre certificat en fonction de votre contexte

II. Installation et configuration de notre registre privé docker

Revenez en arrière (à savoir dans le dosser /docker-registry)

cd ..

Puis, instanciez votre registre privé avec la commande suivante

docker run -d \
-p 5000:5000 \
--restart=always \
--name registry \
-v "$(pwd)"/auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_HTTP_ADDR=0.0.0.0:5000 \
-v "$(pwd)"/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/docker-registry.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/docker-registry.key \
registry

Vérifiez que votre conteneur est bien en cours de fonctionnement :

docker ps
Récapitulatif des étapes précédentes

Si-vous souhaitez vous connecter au shell du conteneur tapez la commande suivante :

docker exec -it id sh

Note : l’image registry, ne supporte pas le shell bash, mais seulement sh

III. Connexion à notre registre local

Saisissez la commande suivante, pour vous connecter au registre local nouvellement créé :

Dans mon cas, les identifiants sont :

  • id : dockerRegistryUser
  • password : password
docker login localhost:5000

A. En cas de problème, lors de la première connexion au registre :

Si vous avez déjà utilisé auparavant docker-hub, alors vos identifiants de connexion vont être utilisés pour vous connecter au registre local ce qui va provoquer l’erreur suivante :

Voici le code erreur en question :

error getting credentials - err: exit status 1, out: `Cannot autolaunch D-Bus without X11 $DISPLAY`

Afin de résoudre ce problème, supprimez manuellement le fichier suivant :

rm /usr/bin/docker-credential-secretservice

Merci à ce sujet stackoverflow qui m’a permit de résoudre le petit problème : https://stackoverflow.com/questions/51153265/docker-login-error-when-manually-logging-into-private-registry

IV. Accès au registre via HTTPS

https://ip:5000/v2

Saisissez vos identifiants pour vous connecter :

V. Création d’une image docker à partir d’un Dockerfile

Revenez dans votre dossier home :

cd ~

Puis créez le dossier suivant :

mkdir imageDockerTest && cd imageDockerTest

Ensuite, créez un fichier Dockerfile :

touch Dockerfile && nano Dockerfile

Nous allons créer une image docker, par l’intermédiaire du bloc de code suivant :

# Utilisation d'une image Ubuntu (par défaut la dernière en date) pour construire notre image docker file
FROM ubuntu 
# Mise à jour des repository distant du container, avant d'installer les paquets requis pour le projet
RUN apt update && apt upgrade -y
# Permet d'éviter d'avoir le bug concernant le choix de la timezone
RUN DEBIAN_FRONTEND="noninteractive" apt-get -y install tzdata 
# Installation des paquets requis pour le projet à savoir git et le service web apache2
RUN apt-get install -y -q git apache2 
# Le conteneur s'éxécutera en se basant sur le service apache2
ENTRYPOINT /usr/sbin/apache2ctl -D FOREGROUND 
# Renommage du fichier de base d'apache2 index.html vers index.html.old
RUN mv /var/www/html/index.html /var/www/html/index.html.old 
# Récupération de mon repository Git avec le mini projet
RUN git clone https://github.com/archidote/get-ready-simple-countdown-html-css-js 
# Copie des fichiers du mini projet web vers la racine de mon serveur web
RUN cd get-ready-simple-countdown-html-css-js && cp * /var/www/html/

N’hésitez pas à utiliser vos propre Dockerfile. Dans le cadre de ce tutoriel, je vais utiliser le Dockefile ci-dessus. Celui-ci permet de créer un serveur web Apache utilisant comme OS de base Ubuntu. Le site sera constitué d’une page affichant un compte à rebours en javascript.

Créez l’image par l’intermédiaire de la commande ci-dessous :

docker build . -t mywebapp

Instanciez un conteneur à partir de cette image :

docker run -d -p 8080:80 <id> 

Et vérifiez que le comportement de celui-ci correspond bien à vos attentes. Dans mon cas, j’ai simplement besoin d’afficher le contenu du site par le biais de mon navigateur comme ci-dessous :

http://localhost:8080/

VI. Publication de notre image sur le registre local

Listez vos images :

docker images

Taguez votre image, en n’oubliant pas de renseignez l’adresse du repository suivi du nom de l’image :

docker tag mywebapp localhost:5000/mywebapp

Puis, téléverser votre image sur votre registre local :

docker push localhost:5000/mywebapp

Récapitulatif des actions précédentes

VII Faites du ménage !

Tintin et le lac aux requins – 1972

Afin de réaliser nos tests dans de bonnes conditions, un peu de ménage s’impose ! Arrêtez le conteneur que vous avez créé plutôt. Je prends comme exemple mon conteneur : mywebapp

docker ps 
docker kill <id>

Puis, supprimez-le :

docker rm -f <id>

Ensuite, supprimez l’image associée à ce conteneur (cette action ne supprime pas l’image stockée dans le registre local) :

docker rmi -f <id> (ce sont deux images liées) 

Voilà, nous avons de nouveau un environnement de travail propre. Listez de nouveau vos images locales, il vous en restera que trois normalement (sauf si vous aviez d’autres images avant de lire cet article) :

Depuis votre navigateur accédez à l’URL ci-dessous. Vous verrez alors que l’image mywebapp est toujours présente sur notre registre local. Nous allons donc l’instancier depuis notre hôte docker et vérifier que celle-ci fonctionne sans accros.

VIII. Instanciation de notre image mywebapp stockée sur notre registre local

docker run -d -p 8080:80 localhost:5000/mywebapp

Nous avons pu récupérer l’image depuis le registre local, et l’instancier par la même occasion !

J’essaye de nouveau d’accéder à mon petit site web :

Non ce n’est pas la même date que l’image plus haut^^

J’espère que cette démonstration vous a plus et que cet article éveillera en vous une certaine sensibilité quant à la souveraineté numérique de votre projet/organisation.

++

Geoffrey Sauvageot-Berland

Geoffrey Sauvageot-Berland

Ingénieur diplômé par l’état en Informatique et Cybersécurité. Généraliste, à l'origine administrateur systèmes et réseaux, j’occupe actuellement un poste d’auditeur en sécurité offensive. J’apprécie également la programmation/automatisation. Fondateur du blog : "Le Guide du SecOps", anciennement "Le Guide du SysOps"

Related Posts

Tester la sécurité d’une API : Un Guide Pratique

Tester la sécurité d’une API : Un Guide Pratique

Weevely – un Webshell interactif polyvalent (cheat sheet)

Weevely – un Webshell interactif polyvalent (cheat sheet)

Reconstruction d’OS non chiffrés : Analyse post-exploitation

Reconstruction d’OS non chiffrés : Analyse post-exploitation

Automatiser l’administration de vos serveurs linux  avec ansible (Démonstration pas à pas)

Automatiser l’administration de vos serveurs linux avec ansible (Démonstration pas à pas)