Comment configurer un registre de docker privé sur Ubuntu 18.04

L’auteur a sélectionné la Apache Software Foundation pour recevoir un don dans le cadre du Write for DOnations programme.

introduction

Docker Registry est une application qui gère le stockage et la diffusion des images du conteneur Docker. Les registres centralisent les images de conteneur et réduisent les temps de construction des développeurs. Les images Docker garantissent le même environnement d’exécution via la virtualisation, mais la création d’une image peut impliquer un investissement de temps considérable. Par exemple, plutôt que d’installer des dépendances et des packages séparément pour utiliser Docker, les développeurs peuvent télécharger une image compressée à partir d’un registre contenant tous les composants nécessaires. En outre, les développeurs peuvent automatiser le transfert d’images vers un registre à l’aide d’outils d’intégration continue, tels que TravisCI, afin de mettre à jour les images de manière transparente au cours de la production et du développement.

Docker dispose également d’un registre public gratuit, Docker Hub, qui peut héberger vos images Docker personnalisées, mais il existe des situations dans lesquelles vous ne souhaitez pas que votre image soit accessible au public. Les images contiennent généralement tout le code nécessaire à l’exécution d’une application. Il est donc préférable d’utiliser un registre privé lorsque vous utilisez un logiciel propriétaire.

Dans ce didacticiel, vous allez configurer et sécuriser votre propre registre Docker privé. Vous utiliserez Docker Compose pour définir les configurations permettant d’exécuter vos applications Docker et Nginx pour transférer le trafic serveur HTTPS au conteneur Docker en cours d’exécution. Une fois ce didacticiel terminé, vous pourrez transférer une image Docker personnalisée dans votre registre privé et extraire l’image de manière sécurisée d’un serveur distant.

Conditions préalables

Avant de commencer ce guide, vous aurez besoin des éléments suivants:

Étape 1 - Installation et configuration du registre Docker

L’outil de ligne de commande Docker est utile pour démarrer et gérer un ou deux conteneurs Docker, mais, pour un déploiement complet, la plupart des applications s’exécutant dans les conteneurs Docker nécessitent l’exécution d’autres composants en parallèle. Par exemple, de nombreuses applications Web consistent en un serveur Web, tel que Nginx, servant le code de l’application, un langage de script interprété, tel que PHP, et un serveur de base de données, tel que MySQL.

Avec Docker Compose, vous pouvez écrire un fichier + .yml + pour configurer la configuration de chaque conteneur et les informations que les conteneurs doivent communiquer. Vous pouvez ensuite utiliser l’outil de ligne de commande + docker-compose + pour exécuter des commandes sur tous les composants de votre application.

Docker Registry est lui-même une application avec plusieurs composants. Vous utiliserez donc Docker Compose pour gérer votre configuration. Pour démarrer une instance du registre, vous allez configurer un fichier + docker-compose.yml + afin de définir l’emplacement où votre registre stockera ses données.

Sur le serveur que vous avez créé pour héberger votre registre Docker privé, vous pouvez créer un répertoire + docker-registry +, vous y rendre, puis créer un sous-dossier + data + avec les commandes suivantes:

mkdir ~/docker-registry && cd $_
mkdir data

Utilisez votre éditeur de texte pour créer le fichier de configuration + docker-compose.yml +:

nano docker-compose.yml

Ajoutez le contenu suivant au fichier, qui décrit la configuration de base d’un registre Docker:

docker-compose.yml

version: '3'

services:
 registry:
   image: registry:2
   ports:
   - "5000:5000"
   environment:
     REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
   volumes:
     - ./data:/data

La section + environment + définit une variable d’environnement dans le conteneur de registre de Docker avec le chemin + / data +. L’application Docker Registry vérifie cette variable d’environnement à son démarrage et commence par conséquent à enregistrer ses données dans le dossier + / data +.

Cependant, comme vous avez inclus les volumes +: - ./data: / data +, Docker commencera à mapper le répertoire + / data + de ce conteneur sur + / data + sur votre serveur de registre. Le résultat final est que les données du registre Docker sont toutes stockées dans + ~ / docker-registry / data + sur le serveur de registre.

La section + ports +, avec la configuration +5000: 5000 +, indique à Docker de mapper le port + 5000 + du serveur sur le port + 5000 + du conteneur en cours d’exécution. Cela vous permet d’envoyer une demande au port + 5000 + sur le serveur et d’envoyer la demande à l’application de registre.

Vous pouvez maintenant démarrer Docker Compose pour vérifier la configuration:

docker-compose up

Vous verrez dans votre sortie des barres de téléchargement montrant que Docker télécharge l’image du registre Docker à partir du propre registre de Docker. Dans une minute ou deux, vous verrez une sortie semblable à celle-ci (les versions peuvent varier):

Output of docker-compose upStarting docker-registry_registry_1 ... done
Attaching to docker-registry_registry_1
registry_1  | time="2018-11-06T18:43:09Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2
registry_1  | time="2018-11-06T18:43:09Z" level=info msg="redis not configured" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2
registry_1  | time="2018-11-06T18:43:09Z" level=info msg="Starting upload purge in 20m0s" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2
registry_1  | time="2018-11-06T18:43:09Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2
registry_1  | time="2018-11-06T18:43:09Z" level=info msg="listening on [::]:5000" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2

Vous aborderez le message d’avertissement + Pas de secret HTTP fourni + plus tard dans ce didacticiel. La sortie indique que le conteneur est en cours de démarrage. La dernière ligne de la sortie indique que l’écoute a commencé avec succès sur le port + 5000 +.

Par défaut, Docker Compose reste en attente de votre entrée. Appuyez sur + CTRL + C + pour fermer votre conteneur de registre Docker.

Vous avez configuré un registre Docker complet à l’écoute sur le port + 5000 +. À ce stade, le registre ne démarre que si vous le lancez manuellement. De plus, Docker Registry n’a pas de mécanisme d’authentification intégré, il est donc actuellement peu sécurisé et totalement ouvert au public. Dans les étapes suivantes, vous allez résoudre ces problèmes de sécurité.

Étape 2 - Configuration de la redirection de port Nginx

Vous avez déjà configuré HTTPS sur votre serveur de registre Docker avec Nginx, ce qui signifie que vous pouvez maintenant configurer la redirection de port de Nginx vers le port + 5000 +. Une fois cette étape terminée, vous pouvez accéder directement à votre registre à l’adresse.

Dans le cadre de la https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-18-04 (Comment sécuriser Nginx avec Let’s Encrypt] Prérequis, vous avez déjà configuré le fichier + / etc / nginx / sites-available / + contenant la configuration de votre serveur.

Ouvrez ce fichier avec votre éditeur de texte:

sudo nano /etc/nginx/sites-available/

Trouvez la ligne + emplacement + existante. Il ressemblera à ceci:

/etc/nginx/sites-available/example.com

...
location / {
 ...
}
...

Vous devez transférer le trafic sur le port + 5000 +, où votre registre sera exécuté. Vous souhaitez également ajouter des en-têtes à la demande dans le registre, qui fournissent des informations supplémentaires du serveur avec chaque demande et réponse. Supprimez le contenu de la section + location + et ajoutez le contenu suivant à cette section:

/etc/nginx/sites-available/example.com

...
location / {
   # 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;
   }

   proxy_pass                          http://localhost:5000;
   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;
}
...

La section + $ http_user_agent + vérifie que la version Docker du client est supérieure à + ​​1.5 + et garantit que le + UserAgent + n’est pas une application + Go +. Puisque vous utilisez la version + 2.0 + du registre, les clients plus anciens ne sont pas supportés. Pour plus d’informations, vous pouvez trouver la configuration de l’en-tête + nginx + dans Document Registry Nginx guide.

Enregistrez et quittez le fichier. Appliquez les modifications en redémarrant Nginx:

sudo service nginx restart

Vous pouvez confirmer que Nginx transfère le trafic sur le port + 5000 + en exécutant le registre:

cd ~/docker-registry
docker-compose up

Dans une fenêtre de navigateur, ouvrez l’URL suivante:

https:///v2

Vous verrez un objet JSON vide ou:

{}

Dans votre terminal, vous verrez une sortie semblable à celle-ci:

Output of docker-compose upregistry_1  | time="2018-11-07T17:57:42Z" level=info msg="response completed" go.version=go1.7.6 http.request.host=cornellappdev.com http.request.id=a8f5984e-15e3-4946-9c40-d71f8557652f http.request.method=GET http.request.remoteaddr=128.84.125.58 http.request.uri="/v2/" http.request.useragent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7" http.response.contenttype="application/json; charset=utf-8" http.response.duration=2.125995ms http.response.status=200 http.response.written=2 instance.id=3093e5ab-5715-42bc-808e-73f310848860 version=v2.6.2
registry_1  | 172.18.0.1 - - [07/Nov/2018:17:57:42 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7"

Vous pouvez voir sur la dernière ligne qu’une requête + GET + a été adressée à + ​​/ v2 / +, qui est le point de terminaison auquel vous avez envoyé une requête de votre navigateur. Le conteneur a reçu la demande que vous avez faite du transfert de port et a renvoyé une réponse + {} +. Le code + 200 + dans la dernière ligne de la sortie signifie que le conteneur a traité la demande avec succès.

Maintenant que vous avez configuré la redirection de port, vous pouvez améliorer la sécurité de votre registre.

Étape 3 - Configuration de l’authentification

Avec les requêtes par proxy Nginx correctement, vous pouvez maintenant sécuriser votre registre avec une authentification HTTP pour gérer les personnes ayant accès à votre registre Docker. Pour ce faire, vous allez créer un fichier d’authentification avec + htpasswd + et y ajouter des utilisateurs. L’authentification HTTP est rapide à configurer et à sécuriser via une connexion HTTPS, ce que le registre utilisera.

Vous pouvez installer le paquet + htpasswd + en lançant ce qui suit:

sudo apt install apache2-utils

Vous allez maintenant créer le répertoire dans lequel vous stockerez nos informations d’authentification et vous y accéderez. + $ _ + se développe jusqu’au dernier argument de la commande précédente, dans ce cas + ~ / docker-registry / auth +:

mkdir ~/docker-registry/auth && cd $_

Ensuite, vous créerez le premier utilisateur comme suit, en remplaçant «+» par le nom d'utilisateur que vous souhaitez utiliser. L'indicateur ` -B ` spécifie le cryptage ` bcrypt +`, qui est plus sécurisé que le cryptage par défaut. Entrez le mot de passe lorsque vous y êtes invité:

htpasswd -Bc registry.password

Vous allez ensuite éditer le fichier + docker-compose.yml + pour indiquer à Docker d’utiliser le fichier que vous avez créé pour authentifier les utilisateurs.

cd ~/docker-registry
nano docker-compose.yml

Vous pouvez ajouter des variables d’environnement et un volume pour le répertoire + auth / + que vous avez créé, en modifiant le fichier + docker-compose.yml + pour indiquer à Docker comment vous souhaitez authentifier les utilisateurs. Ajoutez le contenu en surbrillance suivant au fichier:

docker-compose.yml

version: '3'

services:
 registry:
   image: registry:2
   ports:
   - "5000:5000"
   environment:



     REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
   volumes:

     - ./data:/data

Pour + REGISTRY_AUTH +, vous avez spécifié + htpasswd +, qui est le schéma d’authentification que vous utilisez, et réglez + REGISTRY_AUTH_HTPASSWD_PATH + sur le chemin du fichier d’authentification. Enfin, + REGISTRY_AUTH_HTPASSWD_REALM + signifie le nom du royaume + htpasswd +.

Vous pouvez maintenant vérifier que votre authentification fonctionne correctement en exécutant le registre et en vérifiant qu’il invite les utilisateurs à entrer un nom d’utilisateur et un mot de passe.

docker-compose up

Dans une fenêtre de navigateur, ouvrez + https: /// v2 +.

Après avoir entré «+» et le mot de passe correspondant, vous verrez à nouveau « {} +». Vous avez confirmé la configuration de base de l’authentification: le registre n’a renvoyé le résultat qu’après avoir entré le nom d’utilisateur et le mot de passe corrects. Vous avez maintenant sécurisé votre registre et pouvez continuer à l’utiliser.

Étape 4 - Démarrer Docker Registry en tant que service

Vous voulez vous assurer que votre registre démarrera à chaque démarrage du système. En cas de plantage imprévu du système, vous souhaitez vous assurer que le registre redémarre au redémarrage du serveur. Ouvrez + docker-compose.yml:

nano docker-compose.yml

Ajoutez la ligne de contenu suivante sous + registry: +:

docker-compose.yml

...
 registry:

...

Vous pouvez démarrer votre base de registre en tant que processus en arrière-plan, ce qui vous permettra de quitter la session + ssh + et de conserver le processus:

docker-compose up -d

Avec votre base de registre exécutée en arrière-plan, vous pouvez maintenant préparer Nginx pour le téléchargement de fichiers.

Étape 5 - Augmentation de la taille de téléchargement de fichier pour Nginx

Avant de pouvoir envoyer une image au registre, vous devez vous assurer que celui-ci sera capable de gérer les téléchargements de fichiers volumineux. Bien que Docker divise les images téléchargées volumineuses en couches distinctes, elles peuvent parfois dépasser 1 Go +. Par défaut, Nginx a une limite de téléchargement de fichier de + 1 Mo , vous devez donc modifier le fichier de configuration pour ` nginx ` et définir la taille maximale de téléchargement de fichier sur ` 2 Go +`.

sudo nano /etc/nginx/nginx.conf

Recherchez la section + http + et ajoutez la ligne suivante:

/etc/nginx/nginx.conf

...
http {

       ...
}
...

Enfin, redémarrez Nginx pour appliquer les modifications de configuration:

sudo service nginx restart

Vous pouvez maintenant télécharger de grandes images sur votre base de registre Docker sans erreur Nginx.

Étape 6 - Publication dans votre registre privé Docker

Vous êtes maintenant prêt à publier une image sur votre registre Docker privé, mais vous devez d’abord créer une image. Pour ce tutoriel, vous allez créer une image simple basée sur l’image + ubuntu de Docker Hub. Docker Hub est un registre hébergé publiquement, avec de nombreuses images préconfigurées pouvant être exploitées pour dockerize rapidement. En utilisant l’image + ubuntu, vous allez tester l’affichage poussé et extrait vers votre registre.

Depuis votre serveur * client *, créez une petite image vide à transférer dans votre nouveau registre. Les indicateurs + -i + et + -t + vous donnent un accès interactif au shell dans le conteneur:

docker run -t -i ubuntu /bin/bash

Une fois le téléchargement terminé, vous serez à l’invite de Docker, notez que l’ID de conteneur suivant + root @ + variera. Modifiez rapidement le système de fichiers en créant un fichier nommé + SUCCESS +. À l’étape suivante, vous pourrez utiliser ce fichier pour déterminer si le processus de publication a réussi:

touch /SUCCESS

Quittez le conteneur Docker:

exit

La commande suivante crée une nouvelle image appelée + test-image + en fonction de l’image en cours d’exécution et des modifications apportées. Dans notre cas, l’ajout du fichier + / SUCCESS + est inclus dans la nouvelle image.

Commettez le changement:

docker commit $(docker ps -lq) test-image

À ce stade, l’image n’existe que localement. Vous pouvez maintenant le transférer dans le nouveau registre que vous avez créé. Connectez-vous à votre registre Docker:

docker login https://

Entrez le ++ et le mot de passe correspondant de précédemment. Ensuite, vous marquerez l’image avec l’emplacement du registre privé pour y accéder:

docker tag test-image /test-image

Poussez l’image nouvellement étiquetée dans le registre:

docker push /test-image

Votre sortie ressemblera à ce qui suit:

OutputThe push refers to a repository [/test-image]
e3fbbfb44187: Pushed
5f70bf18a086: Pushed
a3b5c80a4eba: Pushed
7f18b442972b: Pushed
3ce512daaf78: Pushed
7aae4540b42d: Pushed
...

Vous avez vérifié que votre registre gère l’authentification des utilisateurs et permet aux utilisateurs authentifiés de transférer des images dans le registre. Ensuite, vous confirmerez que vous pouvez également extraire des images du registre.

Étape 7 - Extraire de votre registre de dockers privés

Revenez sur votre serveur de registre pour pouvoir tester l’extraction de l’image de votre * client * serveur. Il est également possible de tester cela à partir d’un troisième serveur.

Connectez-vous avec le nom d’utilisateur et le mot de passe que vous avez définis précédemment:

docker login https://

Vous êtes maintenant prêt à extraire l’image. Utilisez votre nom de domaine et votre nom d’image, que vous avez marqués à l’étape précédente:

docker pull /test-image

Docker téléchargera l’image et vous renverra à l’invite. Si vous exécutez l’image sur le serveur de registre, vous verrez le fichier + SUCCESS + créé précédemment:

docker run -it /test-image /bin/bash

Listez vos fichiers dans le shell bash:

ls

Vous verrez le fichier + SUCCESS + que vous avez créé pour cette image:

SUCCESS  bin  boot  dev  etc  home  lib  lib64  media   mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

Vous avez fini de configurer un registre sécurisé sur lequel les utilisateurs peuvent transférer et extraire des images personnalisées.

Conclusion

Dans ce didacticiel, vous configurez votre propre registre Docker privé et publiez une image Docker. Comme indiqué dans l’introduction, vous pouvez également utiliser TravisCI ou un outil de CI similaire pour automatiser le transfert direct vers un registre privé. En utilisant Docker et les registres dans votre flux de travail, vous pouvez vous assurer que l’image contenant le code aura le même comportement sur n’importe quelle machine, en production ou en développement. Pour plus d’informations sur l’écriture de fichiers Docker, vous pouvez lire ce Docker tutorial expliquant le processus.