Comment configurer un registre de docker privé sur Ubuntu 14.04

introduction

Docker est un excellent outil pour déployer vos serveurs. Docker a même un registre public appelé Docker Hub pour stocker les images Docker. Alors que Docker vous permet de télécharger gratuitement vos créations Docker sur leur hub Docker, tout ce que vous téléchargez est également public. Cela pourrait ne pas être la meilleure option pour votre projet.

Ce guide vous montrera comment configurer et sécuriser votre propre registre privé Docker. À la fin de ce didacticiel, vous serez en mesure de transmettre une image Docker personnalisée à votre registre privé et d'extraire l'image en toute sécurité d'un autre hôte.

Ce tutoriel ne couvre pas la conteneurisation de votre propre application, mais seulement la création du registre dans lequel vous pouvez stocker vos déploiements. Si vous voulez savoir comment démarrer avec Docker lui-même (par opposition au registre), vous pouvez lire le didacticiel deHow To Install and Use Docker: Getting Started.

Ce didacticiel a été testé avec le serveur de registre et le client de registre exécutantUbuntu 14.04, mais il peut fonctionner avec d'autres distributions basées sur Debian. Il couvre également la version 2.0 du registre Docker.

Concepts Docker

Si vous n’avez jamais utilisé Docker auparavant, prenez quelques minutes pour passer en revue quelques concepts clés de Docker. Si vous utilisez déjà Docker et souhaitez savoir comment commencer à utiliser votre propre registre, passez à la section suivante.

Pour un rappel sur l'utilisation de Docker, jetez un œil aux excellentsDocker Cheat Sheet.

Docker à la base est un moyen de séparer une application et les dépendances nécessaires à son exécution du système d'exploitation lui-même. Pour rendre cela possible, Docker utilisecontainers etimages. Une image Docker est fondamentalement un modèle pour un système de fichiers. Lorsque vous exécutez une image Docker, une instance de ce système de fichiers est activée et s'exécute sur votre système dans un conteneur Docker. Par défaut, ce conteneur ne peut pas toucher l’image originale ni le système de fichiers de l’hôte sur lequel Docker est exécuté. C’est un environnement autonome.

Quelles que soient les modifications que vous apportez dans le conteneur, elles sont conservées dans ce conteneur et n'affectent pas l'image d'origine. Si vous décidez de conserver ces modifications, vous pouvez «valider» un conteneur dans une image Docker (via la commandedocker commit). Cela signifie que vous pouvez ensuite générer de nouveaux conteneurs qui commencent par le contenu de votre ancien conteneur, sans affecter le conteneur d'origine (ou l'image). Si vous connaissezgit, le flux de travail devrait sembler assez similaire: vous pouvez créer de nouvelles branches (images dans le langage Docker) à partir de n'importe quel conteneur. Lancer une image, c'est un peu comme faire ungit checkout.

Pour continuer l'analogie, exécuter un registre privé Docker revient à exécuter un référentiel Git privé pour vos images Docker.

Conditions préalables

Pour compléter ce tutoriel, vous aurez besoin des éléments suivants:

[[step-1 -—- Installing-package-for-added-security]] == Étape 1 - Installation du package pour plus de sécurité

Pour configurer la sécurité du registre Docker, il est préférable d’utiliserDocker Compose. De cette façon, nous pouvons facilement exécuter le registre Docker dans un conteneur et laisser Nginx gérer la sécurité et la communication avec le monde extérieur dans un autre. Vous devriez déjà l'avoir installé à partir de la section Prérequis.

Puisque nous allons utiliser Nginx pour gérer notre sécurité, nous aurons également besoin d’un emplacement pour stocker la liste des combinaisons de noms d’utilisateur et de mots de passe auxquels nous souhaitons accéder à notre registre. Nous allons installer le packageapache2-utils qui contient l'utilitairehtpasswd qui peut facilement générer des hachages de mot de passe que Nginx peut comprendre:

sudo apt-get -y install apache2-utils

[[step-2 -—- installation-and-configuring-the-docker-registry]] == Étape 2 - Installation et configuration du registre Docker

L'outil de ligne de commande Docker est idéal pour démarrer et gérer un ou deux conteneurs Docker, mais la plupart des applications s'exécutant dans les conteneurs Docker n'existent pas de manière isolée. Pour déployer pleinement la plupart des applications, vous avez besoin de quelques composants fonctionnant en parallèle. Par exemple, la plupart des applications Web sont constituées d’un serveur Web qui gère le code de l’application, d’un langage de script interprété tel que PHP ou Ruby (avec Rails) et d’un serveur de base de données tel que MySQL.

Docker Compose vous permet d'écrire un fichier de configuration.yml pour la configuration de chaque conteneur ainsi que des informations sur la manière dont les conteneurs communiquent entre eux. Vous utilisez ensuite l'outil de ligne de commandedocker-compose pour lancer des commandes à tous les composants qui composent une application.

Le registre Docker étant une application à plusieurs composants, nous utiliserons Docker Compose pour gérer notre configuration.

Pour démarrer un registre de base, la seule configuration nécessaire consiste à définir l'emplacement où votre registre stockera ses données. Commençons par configurer un fichier YAML Docker Compose de base pour créer une instance de base du registre.

Commencez par créer un dossier contenant les fichiers de ce didacticiel et certains des sous-dossiers dont nous aurons besoin:

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

À l'aide de votre éditeur de texte préféré, créez un fichierdocker-compose.yml:

nano docker-compose.yml

Ajoutez le contenu suivant au fichier:

docker-compose.yml

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

La partie intéressante ici est à la fin. La sectionenvironment définit une variable d'environnement dans le conteneur de registre Docker avec le chemin/data. L'application de registre Docker sait vérifier cette variable d'environnement au démarrage et commencer à enregistrer ses données dans le dossier/data en conséquence.

Seulement dans ce cas, le bitvolumes: - ./data:/data indique à Docker que le répertoire/data dans ce conteneur doit en fait mapper vers/data sur notre machine hôte. Le résultat final est que les données du registre Docker sont toutes stockées dans~/docker-registry/data sur notre machine locale.

Allons-y et commençons pour nous assurer que tout est en ordre:

cd ~/docker-registry
docker-compose up

De nombreuses barres de téléchargement se déplacent sur votre écran (Docker télécharge l’image réelle du registre Docker à partir du registre Docker de Docker). Si tout s'est bien passé en une minute ou deux, vous devriez voir un résultat ressemblant à ceci (les versions peuvent varier):

Output of docker-compose upregistry_1 | time="2015-10-18T23:45:58Z" 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." instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="redis not configured" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="using inmemory blob descriptor cache" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="listening on [::]:5000" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="Starting upload purge in 1m0s" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1

Ne vous inquiétez pas du message deNo HTTP secret provided. C'est normal.

Génial! À ce stade, vous avez déjà un registre Docker complet opérationnel et à l'écoute sur le port 5000 (cela a été défini par le bitports: dans le fichierdocker-compose.yml). À ce stade, le registre n'est pas encore très utile - il ne démarre que si vous ouvrez le registre manuellement. De plus, le registre Docker n’a pas de mécanisme d’authentification intégré, il est donc peu sûr et totalement ouvert au public pour le moment.

Docker Compose restera par défaut en attente de votre entrée pour toujours, alors continuez et appuyez surCTRL-C pour fermer votre conteneur de registre Docker.

[[step-3 -—- setting-up-an-nginx-container]] == Étape 3 - Configuration d'un conteneur Nginx

Commençons par résoudre ces problèmes de sécurité. La première étape consiste à configurer une copie de Nginx dans un autre conteneur Docker et à la relier à notre conteneur de registre Docker.

Commençons par créer un répertoire pour stocker notre configuration Nginx:

mkdir ~/docker-registry/nginx

Maintenant, rouvrez votre fichierdocker-compose.yml dans le répertoire~/docker-registry:

nano docker-compose.yml

Collez le texte suivant dans la partie supérieure du fichier:

docker-compose.yml

nginx:
  image: "nginx:1.9"
  ports:
    - 5043:443
  links:
    - registry:registry
  volumes:
    - ./nginx/:/etc/nginx/conf.d:ro

Cela créera un nouveau conteneur Docker basé sur l'image officielle de Nginx. Le bit intéressant ici est la sectionlinks. Il établit automatiquement un «lien» d’un conteneur Docker à un autre. Lorsque le conteneur Nginx démarre, il pourra atteindre le conteneurregistry au nom d'hôteregistry quelle que soit l'adresse IP réelle du conteneurregistry. (Dans les coulisses, Docker insère en fait une entrée dans le fichier/etc/hosts dans le conteneurnginx pour lui indiquer l'adresse IP du conteneurregistry).

La sectionvolumes: est similaire à ce que nous avons fait pour le conteneurregistry. Dans ce cas, cela nous donne un moyen de stocker les fichiers de configuration que nous utiliserons pour Nginx sur notre ordinateur hôte plutôt que dans le conteneur Docker. Le:ro à la fin indique simplement à Docker que le conteneur Nginx ne devrait avoir qu'un accès en lecture seule au système de fichiers hôte.

Votre fichierdocker-compose.yml complet devrait maintenant ressembler à ceci:

docker-compose.yml

nginx:
  image: "nginx:1.9"
  ports:
    - 5043:443
  links:
    - registry:registry
  volumes:
    - ./nginx/:/etc/nginx/conf.d
registry:
  image: registry:2
  ports:
    - 127.0.0.1:5000:5000
  environment:
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
  volumes:
    - ./data:/data

L'exécution dedocker-compose up démarrera désormais deux conteneurs en même temps: un pour le registre Docker et un pour Nginx.

Nous devons toutefois configurer Nginx avant que cela fonctionne. Nous allons donc créer un nouveau fichier de configuration Nginx.

Créez un fichierregistry.conf:

nano ~/docker-registry/nginx/registry.conf

Copiez le texte suivant dans le fichier:

~/docker-registry/nginx/registry.conf

upstream docker-registry {
  server registry:5000;
}

server {
  listen 443;
  server_name myregistrydomain.com;

  # SSL
  # ssl on;
  # ssl_certificate /etc/nginx/conf.d/domain.crt;
  # ssl_certificate_key /etc/nginx/conf.d/domain.key;

  # 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/docker/docker/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 plus add_header
    # auth_basic "registry.localhost";
    # auth_basic_user_file /etc/nginx/conf.d/registry.password;
    # add_header 'Docker-Distribution-Api-Version' 'registry/2.0' 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;
  }
}

Enregistrez et quittez le fichier.

Vous pouvez maintenant installer Nginx et démarrer les deux conteneurs Docker avec une seule commande:

docker-compose up

Nginx n’imprime aucune sortie au démarrage, mais si tout s’est bien passé, vous exécutez maintenant une copie de Nginx qui est configurée pour fournir un proxy à votre conteneurregistry. Pour le tester, utilisonscurl pour envoyer directement une requête HTTP à notre registre Docker, puis adressons une autre requête à notre port Nginx. Si tout est configuré correctement, la sortie sera la même dans les deux cas (au moment de l'écriture, Docker retourne un objet json vide «{}») puisque Nginx transmettra la requête au registre Docker.

Commencez par envoyer une requête HTTP directement au registre Docker:

curl http://localhost:5000/v2/

Au moment de l'écriture, Docker renvoie un objet json vide. Vous devriez donc voir:

Output{}

Envoyez maintenant une requête HTTP au port Nginx:

curl http://localhost:5043/v2/

Vous devriez voir le même résultat:

Output{}

Si tout fonctionne correctement, vous verrez une sortie dans votre terminaldocker-compose qui ressemble également à celle ci-dessous:

Output of docker-compose    registry_1 | time="2015-08-11T10:24:53.746529894Z" level=debug msg="authorizing request" environment=development http.request.host="localhost:5043" http.request.id=55c3e2a6-4f34-4b0b-bc57-11c814b4f4d3 http.request.method=GET http.request.remoteaddr=172.17.42.1 http.request.uri="/v2/" http.request.useragent="curl/7.35.0" instance.id=55634dfc-c9e0-4ec9-9872-6f4930c17759 service=registry version=v2.0.1
    registry_1 | time="2015-08-11T10:24:53.747650205Z" level=info msg="response completed" environment=development http.request.host="localhost:5043" http.request.id=55c3e2a6-4f34-4b0b-bc57-11c814b4f4d3 http.request.method=GET http.request.remoteaddr=172.17.42.1 http.request.uri="/v2/" http.request.useragent="curl/7.35.0" http.response.contenttype="application/json; charset=utf-8" http.response.duration=8.143193ms http.response.status=200 http.response.written=2 instance.id=55634dfc-c9e0-4ec9-9872-6f4930c17759 service=registry version=v2.0.1
    registry_1 | 172.17.0.21 - - [11/Aug/2015:10:24:53 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.35.0"
    nginx_1    | 172.17.42.1 - - [11/Aug/2015:10:24:53 +0000] "GET /v2/ HTTP/1.1" 200 2 "-" "curl/7.35.0" "-"

Si vous voyez des lignes avec le préfixeregistry_ (le nombre après le_ peut être différent sur votre machine) alors tout va bien, et Nginx a réussi à envoyer par proxy notre requête HTTP au registre Docker.

Allez-y et appuyez à nouveau surCTRL-C dans votre terminaldocker-compose pour fermer vos conteneurs Docker.

[[step-4 -—- setting-up-authentication]] == Étape 4 - Configuration de l'authentification

Maintenant que Nginx envoie correctement les serveurs mandataires, laissez-le configurer avec une authentification HTTP afin que nous puissions contrôler qui a accès à notre registre Docker. Pour ce faire, nous allons créer un fichier d'authentification au format Apache (Nginx peut également le lire) via l'utilitairehtpasswd que nous avons installé précédemment et y ajouter des utilisateurs.

Créez le premier utilisateur comme suit, en remplaçantUSERNAME par le nom d'utilisateur que vous souhaitez utiliser:

cd ~/docker-registry/nginx
htpasswd -c registry.password USERNAME

Créez un nouveau mot de passe pour cet utilisateur lorsque vous y êtes invité.

Si vous souhaitez ajouter d'autres utilisateurs à l'avenir, relancez simplement la commande ci-dessus sans l'option-c (lec est pour créer):

htpasswd registry.password USERNAME

À ce stade, nous avons un fichierregistry.password avec nos utilisateurs configurés et un registre Docker disponible. Vous pouvez consulter le fichier à tout moment si vous souhaitez afficher vos utilisateurs (et supprimer des utilisateurs si vous souhaitez révoquer l'accès).

Ensuite, nous devons dire à Nginx d’utiliser ce fichier d’authentification.

Ouvrez~/docker-registry/nginx/registry.conf dans votre éditeur de texte préféré:

nano ~/docker-registry/nginx/registry.conf

Faites défiler vers le milieu du fichier où vous verrez des lignes qui ressemblent à ceci:

~/docker-registry/nginx/registry.conf

# To add basic authentication to v2 use auth_basic setting plus add_header
# auth_basic "registry.localhost";
# auth_basic_user_file /etc/nginx/conf.d/registry.password;
# add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

Décommentez les deux lignes commençant parauth_basic ainsi que la ligne commençant paradd_header en supprimant le caractère# au début
des lignes. Cela devrait alors ressembler à ceci:

~/docker-registry/nginx/registry.conf

# To add basic authentication to v2 use auth_basic setting plus add_header
auth_basic "registry.localhost";
auth_basic_user_file /etc/nginx/conf.d/registry.password;
add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

Nous avons maintenant demandé à Nginx d’activer l’authentification HTTP de base pour toutes les demandes soumises au serveur Docker et d’utiliser le fichier de mots de passe que nous venons de créer.

Rassemblons nos conteneurs pour voir si l’authentification fonctionne:

cd ~/docker-registry
docker-compose up

Répétez le test de boucle précédent:

curl http://localhost:5043/v2/

Vous devriez recevoir un message pour vous plaindre d'être non autorisé:

Output of curl
401 Authorization Required

401 Authorization Required


nginx/1.9.7

Maintenant, essayez d'ajouter le nom d'utilisateur et le mot de passe que vous avez créés précédemment à la requêtecurl:

curl http://USERNAME:PASSWORD@localhost:5043/v2/

Vous devriez obtenir la même sortie que vous obteniez auparavant - l'objet json vide{}. Vous devriez également voir la même sortieregistry_ dans la bornedocker-compose.

Allez-y et utilisezCTRL-C dans le terminaldocker-compose pour arrêter les conteneurs Docker.

[[step-5 -—- setting-up-ssl]] == Étape 5 - Configuration de SSL

À ce stade, le registre est opérationnel derrière Nginx avec l'authentification de base HTTP qui fonctionne. Cependant, la configuration n’est toujours pas très sécurisée car les connexions ne sont pas chiffrées. Vous avez peut-être remarqué les lignes SSL commentées dans le fichier de configuration Nginx créé précédemment.

Permettez-leur de les activer. Tout d’abord, ouvrez le fichier de configuration Nginx pour le modifier:

nano ~/docker-registry/nginx/registry.conf

Utilisez les flèches pour vous déplacer et cherchez les lignes suivantes:

~/docker-registry/nginx/registry.conf

server {
  listen 443;
  server_name myregistrydomain.com;

  # SSL
  # ssl on;
  # ssl_certificate /etc/nginx/conf.d/domain.crt;
  # ssl_certificate_key /etc/nginx/conf.d/domain.key;

Décommentez les lignes sous le commentaire SSL en supprimant les caractères# devant eux. Si vous avez configuré un nom de domaine pour votre serveur, remplacez la valeur deserver_name par votre nom de domaine pendant que vous y êtes. Lorsque vous avez terminé, le haut du fichier devrait ressembler à ceci:

~/docker-registry/nginx/registry.conf

server {
  listen 443;
  server_name myregistrydomain.com;

  # SSL
  ssl on;
  ssl_certificate /etc/nginx/conf.d/domain.crt;
  ssl_certificate_key /etc/nginx/conf.d/domain.key;

Enregistrez le fichier. Nginx est maintenant configuré pour utiliser SSL et recherchera le certificat SSL et les fichiers de clé à/etc/nginx/conf.d/domain.crt et/etc/nginx/conf.d/domain.key respectivement. En raison des mappages que nous avons configurés précédemment dans notre fichierdocker-compose.yml, le chemin/etc/nginx/conf.d/ dans le conteneur Nginx correspond au dossier~/docker-registry/nginx/ sur notre machine hôte, nous allons donc y mettre nos fichiers de certificat .

Si vous avez déjà configuré un certificat SSL ou envisagez d'en acheter un, vous pouvez simplement copier le certificat et les fichiers de clé dans les chemins répertoriés dansregistry.conf (ssl_certificate etssl_certificate_key).

Vous pouvez également obtenir unfree signed SSL certificate.

Sinon, nous devrons utiliser un certificat SSL auto-signé.

Signer votre propre certificat

Étant donné que Docker ne vous permet pas actuellement d'utiliser des certificats SSL auto-signés, cela est un peu plus compliqué que d'habitude - nous devrons également configurer notre système pour agir comme notre propre autorité de signature de certificat.

Pour commencer, passons à notre dossier~/docker-registry/nginx et préparons-nous à créer les certificats:

cd ~/docker-registry/nginx

Générez une nouvelle clé racine:

openssl genrsa -out devdockerCA.key 2048

Générez un certificat racine (entrez ce que vous voulez dans les invites):

openssl req -x509 -new -nodes -key devdockerCA.key -days 10000 -out devdockerCA.crt

Puis générez une clé pour votre serveur (c'est le fichier référencé parssl_certificate_key dans notre configuration Nginx):

openssl genrsa -out domain.key 2048

Nous devons maintenant faire une demande de signature de certificat.

Après avoir tapé cette commande, OpenSSL vous invitera à répondre à quelques questions. Écrivez ce que vous voulez pour les premiers, mais quand OpenSSL vous invite à entrer les“Common Name” make sure to type in the domain or IP of your server.

openssl req -new -key domain.key -out dev-docker-registry.com.csr

Par exemple, si votre registre Docker va être exécuté sur le domainewww.ilovedocker.com, votre entrée devrait ressembler à ceci:

Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:www.ilovedocker.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Ne pas entrer un mot de passe de défi.

Ensuite, nous devons signer la demande de certificat:

openssl x509 -req -in dev-docker-registry.com.csr -CA devdockerCA.crt -CAkey devdockerCA.key -CAcreateserial -out domain.crt -days 10000

Comme les certificats que nous venons de générer ne sont pas vérifiés par une autorité de certification connue (VeriSign, par exemple), nous devons informer les clients qui vont utiliser ce registre Docker qu’il s’agit d’un certificat légitime. Faisons ceci localement sur la machine hôte pour pouvoir utiliser Docker à partir du serveur de registre Docker lui-même:

sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert
sudo cp devdockerCA.crt /usr/local/share/ca-certificates/docker-dev-cert
sudo update-ca-certificates

Redémarrez le démon Docker pour qu'il prenne en compte les modifications apportées à notre magasin de certificats:

sudo service docker restart

[.warning] #Warning: Vous devrez répéter cette étape pour chaque machine qui se connecte à ce registre Docker! Les instructions sur la façon de procéder pour les clients Ubuntu 14.04 sont répertoriées dansStep 9 — Accessing Your Docker Registry from a Client Machine.
#

[[step-6 -—- testing-ssl]] == Étape 6 - Test de SSL

Affichez nos conteneurs Docker via lesdocker-compose up désormais familiers:

cd ~/docker-registry
docker-compose up

Faites un autre test decurl depuis un autre terminal (cette fois en utilisant https uniquement) pour vérifier que notre configuration SSL fonctionne correctement. Gardez à l'esprit que pour que SSL fonctionne correctement, vous devrez utiliser le même nom de domaine que vous avez tapé dans le champCommon Name plus tôt lors de la création de votre certificat SSL.

curl https://USERNAME:PASSWORD@[YOUR-DOMAIN]:5043/v2/

[.Remarque]##

Note: Si vous utilisez un certificat auto-signé, vous verrez l'erreur suivante decurl:

curl: (60) SSL certificate problem: self signed certificate

Utilisez l'option-k pour dire àcurlnot de vérifier avec l'homologue:

curl -k https://USERNAME:PASSWORD@[YOUR-DOMAIN]:5043/v2/

Par exemple, si l'utilisateur et le mot de passe que vous avez définis étaientsammy ettest, et que votre certificat SSL est pourwww.example.com, vous devez saisir ce qui suit:

curl https://sammy:[email protected]:5043/v2/

Si tout s'est bien passé,curl affichera un objet json vide{}, et votre terminaldocker-compose affichera la sortie habituelle deregistry_.

Sinon, revérifiez les étapes SSL et votre fichier de configuration Nginx pour vous assurer que tout est correct.

À ce stade, nous disposons d’un registre Docker 2.0 fonctionnel fonctionnant derrière un serveur Nginx, qui fournit une authentification et un cryptage via SSL. Si votre pare-feu est configuré pour autoriser l'accès au port5043 de l'extérieur, vous devriez pouvoir vous connecter à ce registre Docker à partir de n'importe quelle machinedocker login https://<YOURDOMAIN> et en entrant le nom d'utilisateur et le mot de passe que vous avez définis dans la section précédente .

[[step-7 -—- setting-ssl-port-to-443]] == Étape 7 - Définition du port SSL sur 443

Quelques étapes de plus à faire avant que nous ayons terminé: changez le port pour utiliser le port SSL standard de443 (facultatif) et configurezdocker-compose pour démarrer cet ensemble de conteneurs au démarrage.

Commençons par configurer notre conteneur Nginx dockérisé pour l’écoute sur le port 443 (le port standard pour SSL) plutôt que sur le port non standard 5043 que nous utilisions jusqu’à présent. Les ports inférieurs à 1024 sont des ports «privilégiés» sous Linux, ce qui signifie que nous allons devoir exécuter notre conteneurdocker-compose en tant que root.

Ouvrez d'aborddocker-compose.yml dans un éditeur de texte:

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

Sous la section Nginx, vous verrez une sectionports:, changez la ligne- 5043:443 (ceci mappe le port 5043 sur notre machine hôte au port 443 à l'intérieur du conteneur Nginx) en- 443:443 afin que notre Le port 443 du conteneur Nginx est mappé sur le port 443 de notre machine hôte. Une fois terminé, vosdocker-compose.ymldevraient ressembler à ceci:

~/docker-registry/docker-compose.yml

nginx:
  image: "nginx:1.9"
  ports:
    - 443:443
  links:
    - registry:registry
  volumes:
    - ./nginx/:/etc/nginx/conf.d:ro
registry:
  image: registry:2
  ports:
    - 127.0.0.1:5000:5000
  environment:
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
  volumes:
    - ./data:/data

Tuez votre sessiondocker-compose viaCTRL-C si elle est toujours en cours d'exécution et redémarrez-la sur le port 443:

sudo docker-compose up

[.note] #Note: Seuls les utilisateurs root peuvent écouter les ports inférieurs à 1024. Notez que vous devez utilisersudo cette fois avec la commandedocker-compose pour que Nginx puisse s'exécuter sur le port SSL par défaut 443.
#

Vous devriez voirdocker-compose démarrer comme d'habitude.

Essayons un autre testcurl en utilisant notre nom de domaine, mais cette fois nous ne spécifierons pas les:5043 dans l'URL:

curl https://:@YOUR-DOMAIN/v2/

Si tout s'est bien passé, vous devriez voir la sortie habituelle deregistry_ dans votre terminaldocker-compose. Vous pouvez également essayer d'exécuter cette même commandecurl depuis une autre machine pour vous assurer que votre port 443 est exposé au monde extérieur.

Allez-y et utilisezCTRL-C dans le terminaldocker-compose pour arrêter les conteneurs Docker avant de passer à l'étape suivante.

[[step-8 -—- starting-docker-registry-as-a-service]] == Étape 8 - Démarrage de Docker Registry as a Service

Si tout semble bon, allons-y et créons un scriptUpstart afin que notre registre Docker démarre chaque fois que le système démarre.

Commençons par supprimer tous les conteneurs existants, déplaçons notre registre Docker vers un emplacement à l’échelle du système et modifions ses autorisations en tant qu’utilisateur root:

cd ~/docker-registry
docker-compose rm   # this removes the existing containers
sudo mv ~/docker-registry /docker-registry
sudo chown -R root: /docker-registry

Ensuite, utilisez votre éditeur de texte favori pour créer un script Upstart:

sudo nano /etc/init/docker-registry.conf

Ajoutez le contenu suivant pour créer le script Upstart (obtenir Upstart pour surveiller correctement les conteneurs Docker est un peu difficile, consultezthis blog post si vous souhaitez plus d'informations sur ce que fait ce script Upstart):

/etc/init/docker-registry.conf

description "Docker Registry"

start on runlevel [2345]
stop on runlevel [016]

respawn
respawn limit 10 5

chdir /docker-registry

exec /usr/local/bin/docker-compose up

Pour plus d'informations sur les scripts Upstart, veuillez lirethis tutorial.

Essayons notre nouveau script Upstart en lançant:

sudo service docker-registry start

Vous devriez voir quelque chose comme ça:

docker-registry start/running, process 25303

Vous pouvez vérifier que le serveur est en cours d'exécution en exécutant:

docker ps

La sortie doit ressembler à ce qui suit (notez que les noms commencent tous pardockerregistry_

CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                          NAMES
d4b6fef0b4d1        nginx:1.9           "nginx -g 'daemon of   2 minutes ago       Up 2 minutes        80/tcp, 0.0.0.0:443->443/tcp   dockerregistry_nginx_1
77668352bd39        registry:2          "registry cmd/regist   2 minutes ago       Up 2 minutes        127.0.0.1:5000->5000/tcp       dockerregistry_registry_1

Upstart enregistrera la sortie de la commandedocker-compose dans/var/log/upstart/docker-registry.log. Pour notre test final, regardons en direct le fichier journal avectail (lesudo est nécessaire car les journaux de démarrage sont écrits en tant qu'utilisateur root):

sudo tail -f /var/log/upstart/docker-registry.log

Vous devriez voir la sortie habituelle deregistry_. À partir d'un autre terminal ou d'une autre machine, lancez notre testcurl maintenant familier:

curl https://:@[YOUR-DOMAIN]/v2/

Si tout fonctionne correctement, curl affichera un{} sur votre terminal et vous devriez voir l'habituel:

registry_1 | time="2015-08-12T08:01:12.241887501Z" level=debug msg="authorizing request" environment=development http.request.host=docker.meatflavoredbeer.com http.request.id=e8d69e16-9448-4c48-afd8-57b1f1302742 http.request.method=GET http.request.remoteaddr=106.1.247.4 http.request.uri="/v2/" http.request.useragent="curl/7.37.1" instance.id=14d4727b-fda1-463f-8d0e-181f4c70cb17 service=registry version=v2.0.1
registry_1 | time="2015-08-12T08:01:12.242206499Z" level=info msg="response completed" environment=development http.request.host=docker.meatflavoredbeer.com http.request.id=e8d69e16-9448-4c48-afd8-57b1f1302742 http.request.method=GET http.request.remoteaddr=106.1.247.4 http.request.uri="/v2/" http.request.useragent="curl/7.37.1" http.response.contenttype="application/json; charset=utf-8" http.response.duration=3.359883ms http.response.status=200 http.response.written=2 instance.id=14d4727b-fda1-463f-8d0e-181f4c70cb17 service=registry version=v2.0.1
registry_1 | 172.17.0.4 - - [12/Aug/2015:08:01:12 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.37.1"
nginx_1    | 106.1.247.4 - nik [12/Aug/2015:08:01:12 +0000] "GET /v2/ HTTP/1.1" 200 2 "-" "curl/7.37.1" "-"

[[step-9 -—- access-your-docker-registry-from-a-client-machine]] == Étape 9 - Accéder à votre registre Docker à partir d'une machine client

Pour accéder à votre registre Docker depuis un autre ordinateur, ajoutez d’abord le certificat SSL que vous avez créé précédemment à la nouvelle machine cliente. Le fichier souhaité se trouve à~/docker-registry/nginx/devdockerCA.crt.

Vous pouvez le copier directement sur le nouvel ordinateur ou utiliser les instructions ci-dessous pour le copier et le coller:

Sur lesregistry server, affichez le certificat:

sudo cat /docker-registry/nginx/devdockerCA.crt

Vous obtiendrez une sortie qui ressemble à ceci:

Output of sudo cat /docker-registry/nginx/devdockerCA.crt-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJANiXy7fHSPrmMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTQwOTIxMDYwODE2WhcNNDIwMjA2MDYwODE2WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuK4kNFaY3k/0RdKRK1XLj9+IrpR7WW5lrNaFB0OIiItHV9FjyuSWK2mj
ObR1IWJNrVSqWvfZ/CLGay6Lp9DJvBbpT68dhuS5xbVw3bs3ghB24TntDYhHMAc8
GWor/ZQTzjccHUd1SJxt5mGXalNHUharkLd8mv4fAb7Mh/7AFP32W4X+scPE2bVH
OJ1qH8ACo7pSVl1Ohcri6sMp01GoELyykpXu5azhuCnfXLRyuOvQb7llV5WyKhq+
SjcE3c2C+hCCC5g6IzRcMEg336Ktn5su+kK6c0hoD0PR/W0PtwgH4XlNdpVFqMST
vthEG+Hv6xVGGH+nTszN7F9ugVMxewIDAQABo1AwTjAdBgNVHQ4EFgQULek+WVyK
dJk3JIHoI4iVi0FPtdwwHwYDVR0jBBgwFoAULek+WVyKdJk3JIHoI4iVi0FPtdww
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkignESZcgr4dBmVZqDwh
YsrKeWSkj+5p9eW5hCHJ5Eg2X8oGTgItuLaLfyFWPS3MYWWMzggxgKMOQM+9o3+k
oH5sUmraNzI3TmAtkqd/8isXzBUV661BbSV0obAgF/ul5v3Tl5uBbCXObC+NUikM
O0C3fDmmeK799AM/hP5CTDehNaFXABGoVRMSlGYe8hZqap/Jm6AaKThV4g6n4F7M
u5wYtI9YDMsxeVW6OP9ZfvpGZW/n/88MSFjMlBjFfFsorfRd6P5WADhdfA6CBECG
LP83r7/MhqO06EOpsv4n2CJ3yoyqIr1L1+6C7Erl2em/jfOb/24y63dj/ATytt2H
6g==
-----END CERTIFICATE-----

Copiez cette sortie dans votre presse-papiers et connectez-vous à votre ordinateur client.

Sur lesclient machine, créez le répertoire des certificats:

sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert

Ouvrez le fichier de certificat pour le modifier:

sudo nano /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt

Collez le contenu du certificat.

Vérifiez que le fichier a été correctement enregistré sur la machine client en affichant le fichier:

cat /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt

Si tout fonctionne correctement, vous verrez le même texte que précédemment:

Output of cat /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJANiXy7fHSPrmMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
...
...
LP83r7/MhqO06EOpsv4n2CJ3yoyqIr1L1+6C7Erl2em/jfOb/24y63dj/ATytt2H
6g==
-----END CERTIFICATE-----

Maintenant, mettez à jour les certificats:

sudo update-ca-certificates

Vous devriez obtenir une sortie qui ressemble à ce qui suit (notez le "1 ajouté"):

Output of sudo update-ca-certificatesUpdating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.

Si Docker n’est pas encore installé sur le client, faites-le maintenant (voir la section Conditions préalables).

Redémarrez Docker pour s’assurer de recharger les certificats de l’autorité de certification du système.

sudo service docker restart

Vous devriez maintenant pouvoir vous connecter à votre registre Docker à partir de la machine cliente:

docker login https://YOUR-DOMAIN

Notez que vous utilisezhttps://. Entrez le nom d'utilisateur et le mot de passe que vous avez définis précédemment (indiquez ce que vous souhaitez pour un courrier électronique si vous y êtes invité).

Output of docker loginUsername: USERNAME
Password: PASSWORD
Email:
Account created. Please see the documentation of the registry http://localhost:5000/v1/ for instructions how to activate it.

Vous devriez voir le message suivant:

Output of docker loginLogin Succeeded

À ce stade, votre base de registre Docker est opérationnelle! Faisons une image de test à transmettre au registre.

[[step-10 -—- publish-to-your-private-docker-registry]] == Étape 10 - Publier sur votre registre Docker privé

Vous êtes maintenant prêt à publier une image dans votre registre privé Docker, mais vous devez d'abord créer une image. Nous allons créer une image simple basée sur l'imageubuntu de Docker Hub.

À partir de vosclient machine, créez une petite image vide à pousser vers notre nouveau registre.

docker run -t -i ubuntu /bin/bash

Une fois le téléchargement terminé, vous serez à l’invite de Docker. Modifions rapidement le système de fichiers en créant un fichier appeléSUCCESS:

touch /SUCCESS

Quittez le conteneur Docker:

exit

Commettez le changement:

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

Cette commande crée une nouvelle image appeléetest-image basée sur l'image déjà en cours d'exécution ainsi que les modifications que vous avez apportées. Dans notre cas, l'ajout du fichier/SUCCESS est inclus dans la nouvelle image.

Cette image n’existe que localement, vous devez donc la placer dans le nouveau registre que nous avons créé.

Lors de l'étape précédente, vous vous êtes connecté à votre registre privé Docker. Si vous n'êtes pas encore connecté, reconnectez-vous (notez que vous souhaitez utiliserhttps://):

docker login https://YOUR-DOMAIN

Entrez le nom d'utilisateur et le mot de passe que vous avez définis précédemment:

Username: USERNAME
Password: PASSWORD
Email:
Account created. Please see the documentation of the registry http://localhost:5000/v1/ for instructions how to activate it.

Docker dispose d'un mécanisme inhabituel pour spécifier le registre vers lequel pousser. Vous devez baliser une image avec l’emplacement du registre privé pour pouvoir y accéder. Etiquetons notre image dans notre registre privé:

docker tag test-image [YOUR-DOMAIN]/test-image

Notez que vous utilisez d'abord le nom local de l'image, puis la balise que vous souhaitez y ajouter. La balise utilisenothttps://, uniquement le nom de domaine, de port et d'image.

Nous pouvons maintenant transmettre cette image à notre registre. Cette fois, nous utilisons uniquement le nom de la balise:

docker push [YOUR-DOMAIN]/test-image

Cela prendra un moment pour télécharger sur le serveur de registre. Vous devriez voir une sortie qui se termine par quelque chose de similaire au suivant:

Output of docker pushlatest: digest: sha256:5ea1cfb425544011a3198757f9c6b283fa209a928caabe56063f85f3402363b4 size: 8008

[[step-11 -—- pull-from-your-docker-registry]] == Étape 11 - Extraire de votre registre Docker

Pour vous assurer que tout fonctionne, revenons à notre serveur d'origine (où vous avez installé le registre Docker) et extrayez l'image que nous venons de transmettre du client. Vous pouvez également tester cela à partir d'un troisième serveur.

Si Docker n’est pas installé sur votre serveur test pull, revenez en arrière et suivez les instructions d’installation (et s’il s’agit d’un troisième serveur, les instructions SSL) à l’étape 6.

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

docker login https://[YOUR-DOMAIN]

Et maintenant, tirez l'image. Vous ne voulez que le nom de l'image «tag», qui comprend le nom de domaine, le port et le nom de l'image (mais pashttps://):

docker pull [YOUR-DOMAIN]/test-image

Docker effectuera des téléchargements et vous ramènera à l'invite. Si vous exécutez l’image sur la nouvelle machine, vous verrez que le fichier SUCCESS que nous avons créé précédemment se trouve:

docker run -t -i [YOUR-DOMAIN]/test-image /bin/bash

Listez vos fichiers dans le shell bash:

ls

Vous devriez voir le fichierSUCCESS que nous avons créé précédemment pour cette image:

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

Conclusion

Toutes nos félicitations! Vous venez d’utiliser votre propre registre privé Docker pour pousser et tirer votre premier conteneur Docker!

Joyeux dockering!