⚠️ Traduction non officielle - Cette documentation est une traduction communautaire non officielle de Docker.

Gérer les données sensibles avec les secrets Docker

À propos des secrets

En termes de services Docker Swarm, un secret est un blob de données, comme un mot de passe, une clé privée SSH, un certificat SSL, ou une autre donnée qui ne devrait pas être transmise sur un réseau ou stockée non chiffrée dans un Dockerfile ou dans le code source de votre application. Vous pouvez utiliser les secrets Docker pour gérer centralement ces données et les transmettre de manière sécurisée uniquement aux conteneurs qui ont besoin d'y accéder. Les secrets sont chiffrés pendant le transit et au repos dans un swarm Docker. Un secret donné n'est accessible qu'aux services auxquels un accès explicite a été accordé, et seulement pendant que ces tâches de service sont en cours d'exécution.

Vous pouvez utiliser les secrets pour gérer toutes les données sensibles dont un conteneur a besoin à l'exécution mais que vous ne voulez pas stocker dans l'image ou dans le contrôle de source, comme :

  • Noms d'utilisateur et mots de passe
  • Certificats et clés TLS
  • Clés SSH
  • Autres données importantes comme le nom d'une base de données ou d'un serveur interne
  • Chaînes génériques ou contenu binaire (jusqu'à 500 ko de taille)
Note

Les secrets Docker ne sont disponibles que pour les services swarm, pas pour les conteneurs autonomes. Pour utiliser cette fonctionnalité, considérez adapter votre conteneur pour qu'il fonctionne comme un service. Les conteneurs avec état peuvent typiquement fonctionner avec une échelle de 1 sans changer le code du conteneur.

Un autre cas d'usage pour utiliser les secrets est de fournir une couche d'abstraction entre le conteneur et un ensemble d'identifiants. Considérez un scénario où vous avez des environnements de développement, test et production séparés pour votre application. Chacun de ces environnements peut avoir des identifiants différents, stockés dans les swarms de développement, test et production avec le même nom de secret. Vos conteneurs n'ont besoin de connaître que le nom du secret pour fonctionner dans les trois environnements.

Vous pouvez également utiliser les secrets pour gérer des données non sensibles, comme les fichiers de configuration. Cependant, Docker supporte l'utilisation de configs pour stocker des données non sensibles. Les configs sont montées dans le système de fichiers du conteneur directement, sans l'utilisation d'un disque RAM.

Support Windows

Docker inclut le support des secrets sur les conteneurs Windows. Là où il y a des différences dans les implémentations, elles sont signalées dans les exemples ci-dessous. Gardez à l'esprit les différences notables suivantes :

  • Microsoft Windows n'a pas de pilote intégré pour gérer les disques RAM, donc dans les conteneurs Windows en cours d'exécution, les secrets sont persistés en texte clair sur le disque racine du conteneur. Cependant, les secrets sont explicitement supprimés lorsqu'un conteneur s'arrête. De plus, Windows ne supporte pas la persistance d'un conteneur en cours d'exécution comme image en utilisant docker commit ou des commandes similaires.

  • Sur Windows, nous recommandons d'activer BitLocker sur le volume contenant le répertoire racine Docker sur la machine hôte pour s'assurer que les secrets pour les conteneurs en cours d'exécution sont chiffrés au repos.

  • Les fichiers secrets avec des cibles personnalisées ne sont pas directement bind-montés dans les conteneurs Windows, car Windows ne supporte pas les bind-mounts de fichiers non-répertoires. Au lieu de cela, les secrets pour un conteneur sont tous montés dans C:\ProgramData\Docker\internal\secrets (un détail d'implémentation sur lequel les applications ne devraient pas compter) dans le conteneur. Des liens symboliques sont utilisés pour pointer de là vers la cible désirée du secret dans le conteneur. La cible par défaut est C:\ProgramData\Docker\secrets.

  • Lors de la création d'un service qui utilise des conteneurs Windows, les options pour spécifier UID, GID et mode ne sont pas supportées pour les secrets. Les secrets ne sont actuellement accessibles que par les administrateurs et les utilisateurs avec un accès system dans le conteneur.

Comment Docker gère les secrets

Lorsque vous ajoutez un secret au swarm, Docker envoie le secret au gestionnaire swarm via une connexion TLS mutuelle. Le secret est stocké dans le log Raft, qui est chiffré. L'ensemble du log Raft est répliqué à travers les autres gestionnaires, assurant les mêmes garanties de haute disponibilité pour les secrets que pour le reste des données de gestion swarm.

Lorsque vous accordez à un service nouvellement créé ou en cours d'exécution l'accès à un secret, le secret déchiffré est monté dans le conteneur dans un système de fichiers en mémoire. L' emplacement du point de montage dans le conteneur par défaut est /run/secrets/<secret_name> dans les conteneurs Linux, ou C:\ProgramData\Docker\secrets dans les conteneurs Windows. Vous pouvez également spécifier un emplacement personnalisé.

Vous pouvez mettre à jour un service pour lui accorder l'accès à des secrets supplémentaires ou révoquer son accès à un secret donné à tout moment.

Un nœud n'a accès aux secrets (chiffrés) que si le nœud est un gestionnaire swarm ou s'il exécute des tâches de service auxquelles l'accès au secret a été accordé. Lorsqu'une tâche de conteneur s'arrête, les secrets déchiffrés partagés avec elle sont démontés du système de fichiers en mémoire pour ce conteneur et supprimés de la mémoire du nœud.

Si un nœud perd la connectivité avec le swarm pendant qu'il exécute un conteneur de tâche avec accès à un secret, le conteneur de tâche a toujours accès à ses secrets, mais ne peut pas recevoir de mises à jour jusqu'à ce que le nœud se reconnecte au swarm.

Vous pouvez ajouter ou inspecter un secret individuel à tout moment, ou lister tous les secrets. Vous ne pouvez pas supprimer un secret qu'un service en cours d'exécution utilise. Voir Faire tourner un secret pour une façon de supprimer un secret sans perturber les services en cours d'exécution.

Pour mettre à jour ou revenir en arrière sur les secrets plus facilement, considérez ajouter un numéro de version ou une date au nom du secret. Ceci est facilité par la capacité de contrôler le point de montage du secret dans un conteneur donné.

En savoir plus sur les commandes docker secret

Utilisez ces liens pour lire à propos de commandes spécifiques, ou continuez vers l' exemple sur l'utilisation des secrets avec un service.

Exemples

Cette section inclut trois exemples gradués qui illustrent comment utiliser les secrets Docker. Les images utilisées dans ces exemples ont été mises à jour pour faciliter l'utilisation des secrets Docker. Pour découvrir comment modifier vos propres images de manière similaire, voir Intégrer le support des secrets Docker dans vos images.

Note

Ces exemples utilisent un swarm à moteur unique et des services non mis à l'échelle pour la simplicité. Les exemples utilisent des conteneurs Linux, mais les conteneurs Windows supportent également les secrets. Voir Support Windows.

Définir et utiliser les secrets dans les fichiers compose

Les commandes docker-compose et docker stack supportent toutes deux la définition de secrets dans un fichier compose. Voir la référence du fichier Compose pour les détails.

Exemple simple : Commencer avec les secrets

Cet exemple simple montre comment les secrets fonctionnent en quelques commandes seulement. Pour un exemple du monde réel, continuez vers Exemple intermédiaire : Utiliser les secrets avec un service Nginx.

  1. Ajoutez un secret à Docker. La commande docker secret create lit l'entrée standard car le dernier argument, qui représente le fichier à partir duquel lire le secret, est défini à -.

    $ printf "This is a secret" | docker secret create my_secret_data -
    
  2. Créez un service redis et accordez-lui l'accès au secret. Par défaut, le conteneur peut accéder au secret à /run/secrets/<secret_name>, mais vous pouvez personnaliser le nom de fichier sur le conteneur en utilisant l'option target.

    $ docker service  create --name redis --secret my_secret_data redis:alpine
    
  3. Vérifiez que la tâche fonctionne sans problèmes en utilisant docker service ps. Si tout fonctionne, la sortie ressemble à ceci :

    $ docker service ps redis
    
    ID            NAME     IMAGE         NODE              DESIRED STATE  CURRENT STATE          ERROR  PORTS
    bkna6bpn8r1a  redis.1  redis:alpine  ip-172-31-46-109  Running        Running 8 seconds ago  
    

    S'il y avait une erreur, et que la tâche échouait et redémarrait de manière répétée, vous verriez quelque chose comme ceci :

    $ docker service ps redis
    
    NAME                      IMAGE         NODE  DESIRED STATE  CURRENT STATE          ERROR                      PORTS
    redis.1.siftice35gla      redis:alpine  moby  Running        Running 4 seconds ago                             
     \_ redis.1.whum5b7gu13e  redis:alpine  moby  Shutdown       Failed 20 seconds ago      "task: non-zero exit (1)"  
     \_ redis.1.2s6yorvd9zow  redis:alpine  moby  Shutdown       Failed 56 seconds ago      "task: non-zero exit (1)"  
     \_ redis.1.ulfzrcyaf6pg  redis:alpine  moby  Shutdown       Failed about a minute ago  "task: non-zero exit (1)"  
     \_ redis.1.wrny5v4xyps6  redis:alpine  moby  Shutdown       Failed 2 minutes ago       "task: non-zero exit (1)"
    
  4. Obtenez l'ID du conteneur de tâche du service redis en utilisant docker ps, afin que vous puissiez utiliser docker container exec pour vous connecter au conteneur et lire le contenu du fichier de données secrètes, qui par défaut est lisible par tous et a le même nom que le nom du secret. La première commande ci-dessous illustre comment trouver l'ID du conteneur, et les deuxième et troisième commandes utilisent la complétion shell pour faire cela automatiquement.

    $ docker ps --filter name=redis -q
    
    5cb1c2348a59
    
    $ docker container exec $(docker ps --filter name=redis -q) ls -l /run/secrets
    
    total 4
    -r--r--r--    1 root     root            17 Dec 13 22:48 my_secret_data
    
    $ docker container exec $(docker ps --filter name=redis -q) cat /run/secrets/my_secret_data
    
    This is a secret
    
  5. Vérifiez que le secret n'est plus disponible si vous committez le conteneur.

    $ docker commit $(docker ps --filter name=redis -q) committed_redis
    
    $ docker run --rm -it committed_redis cat /run/secrets/my_secret_data
    
    cat: can't open '/run/secrets/my_secret_data': No such file or directory
    
  6. Essayez de supprimer le secret. La suppression échoue car le service redis est en cours d'exécution et a accès au secret.

    $ docker secret ls
    
    ID                          NAME                CREATED             UPDATED
    wwwrxza8sxy025bas86593fqs   my_secret_data      4 hours ago         4 hours ago
    
    
    $ docker secret rm my_secret_data
    
    Error response from daemon: rpc error: code = 3 desc = secret
    'my_secret_data' is in use by the following service: redis
    
  7. Supprimez l'accès au secret du service en cours d'exécution en mettant à jour le service.

    $ docker service update --secret-rm my_secret_data redis
    
  8. Répétez les étapes 3 et 4 à nouveau, vérifiant que le service n'a plus accès au secret. L'ID du conteneur est différent, car la commande service update redéploie le service.

    $ docker container exec -it $(docker ps --filter name=redis -q) cat /run/secrets/my_secret_data
    
    cat: can't open '/run/secrets/my_secret_data': No such file or directory
    
  9. Arrêtez et supprimez le service, et supprimez le secret de Docker.

    $ docker service rm redis
    
    $ docker secret rm my_secret_data
    

Exemple simple : Utiliser les secrets dans un service Windows

C'est un exemple très simple qui montre comment utiliser les secrets avec un service Microsoft IIS en cours d'exécution sur Docker pour Windows en cours d'exécution sur Microsoft Windows 10. C'est un exemple naïf qui stocke la page web dans un secret.

Cet exemple suppose que vous avez PowerShell installé.

  1. Enregistrez le suivant dans un nouveau fichier index.html.

    <html lang="en">
      <head><title>Hello Docker</title></head>
      <body>
        <p>Hello Docker! You have deployed a HTML page.</p>
      </body>
    </html>
  2. Si vous ne l'avez pas déjà fait, initialisez ou rejoignez le swarm.

    > docker swarm init
    
  3. Enregistrez le fichier index.html en tant que secret swarm nommé homepage.

    > docker secret create homepage index.html
    
  4. Créez un service IIS et accordez-lui l'accès au secret homepage.

    > docker service create `
        --name my-iis `
        --publish published=8000,target=8000 `
        --secret src=homepage,target="\inetpub\wwwroot\index.html" `
        microsoft/iis:nanoserver
    
    Note

    Il n'y a techniquement aucune raison d'utiliser des secrets pour cet exemple; configs sont un meilleur choix. Cet exemple est uniquement pour illustration.

  5. Accédez au service IIS à http://localhost:8000/. Il devrait servir le contenu HTML de la première étape.

  6. Supprimez le service et le secret.

    > docker service rm my-iis
    > docker secret rm homepage
    > docker image remove secret-test
    

Exemple intermédiaire : Utiliser les secrets avec un service Nginx

Cet exemple est divisé en deux parties. La première partie est tout à propos de générer le certificat de site et ne concerne pas Docker secrets du tout, mais il met en place la deuxième partie, où vous stockez et utilisez le certificat de site et la configuration Nginx comme secrets.

Générer le certificat de site

Générez une autorité de certification racine et un certificat TLS et clé pour votre site. Pour les sites de production, vous pouvez vouloir utiliser un service tel que Let's Encrypt pour générer le certificat et la clé TLS, mais cet exemple utilise des outils en ligne de commande. Cette étape est un peu compliquée, mais est uniquement une étape de configuration pour que vous ayez quelque chose à stocker comme secret Docker. Si vous voulez sauter ces sous-étapes, vous pouvez utiliser Let's Encrypt pour générer la clé et le certificat du site, nommez les fichiers site.key et site.crt, et passez à Configurer le conteneur Nginx.

  1. Générez une clé racine.

    $ openssl genrsa -out "root-ca.key" 4096
    
  2. Générez un CSR à l'aide de la clé racine.

    $ openssl req \
              -new -key "root-ca.key" \
              -out "root-ca.csr" -sha256 \
              -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA'
    
  3. Configurez l'autorité de certification racine. Modifiez un nouveau fichier appelé root-ca.cnf et collez le contenu suivant dans le fichier. Cela contraint l'autorité de certification racine à signer des certificats de feuille et non des CAs intermédiaires.

    [root_ca]
    basicConstraints = critical,CA:TRUE,pathlen:1
    keyUsage = critical, nonRepudiation, cRLSign, keyCertSign
    subjectKeyIdentifier=hash
  4. Signez le certificat.

    $ openssl x509 -req  -days 3650  -in "root-ca.csr" \
                   -signkey "root-ca.key" -sha256 -out "root-ca.crt" \
                   -extfile "root-ca.cnf" -extensions \
                   root_ca
    
  5. Générez la clé du site.

    $ openssl genrsa -out "site.key" 4096
    
  6. Générez le certificat du site et signez-le avec la clé du site.

    $ openssl req -new -key "site.key" -out "site.csr" -sha256 \
              -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost'
    
  7. Configurez le certificat du site. Modifiez un nouveau fichier appelé site.cnf et collez le contenu suivant dans le fichier. Cela contraint le certificat du site pour qu'il puisse uniquement être utilisé pour authentifier un serveur et ne peut pas être utilisé pour signer des certificats.

    [server]
    authorityKeyIdentifier=keyid,issuer
    basicConstraints = critical,CA:FALSE
    extendedKeyUsage=serverAuth
    keyUsage = critical, digitalSignature, keyEncipherment
    subjectAltName = DNS:localhost, IP:127.0.0.1
    subjectKeyIdentifier=hash
  8. Signez le certificat du site.

    $ openssl x509 -req -days 750 -in "site.csr" -sha256 \
        -CA "root-ca.crt" -CAkey "root-ca.key"  -CAcreateserial \
        -out "site.crt" -extfile "site.cnf" -extensions server
    
  9. Les fichiers site.csr et site.cnf ne sont pas nécessaires au service Nginx, mais vous en avez besoin si vous voulez générer un nouveau certificat de site. Protégez le fichier root-ca.key.

Configurer le conteneur Nginx

  1. Produisez une configuration Nginx très basique qui sert des fichiers statiques sur HTTPS. Le certificat et la clé sont stockés comme secrets Docker pour qu'ils puissent être tournés facilement.

    Dans le répertoire actuel, créez un nouveau fichier appelé site.conf avec le contenu suivant :

    server {
        listen                443 ssl;
        server_name           localhost;
        ssl_certificate       /run/secrets/site.crt;
        ssl_certificate_key   /run/secrets/site.key;
    
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
    }
  2. Créez trois secrets, représentant la clé, le certificat et site.conf. Vous pouvez stocker n'importe quel fichier comme secret tant que il est inférieur à 500 Ko. Cela vous permet de découpler la clé, le certificat et la configuration des services qui les utilisent. Dans chacun de ces commandes, le dernier argument représente le chemin du fichier à partir duquel lire le secret sur le système de fichiers de la machine hôte. Dans ces exemples, le nom du secret et le nom de fichier sont les mêmes.

    $ docker secret create site.key site.key
    
    $ docker secret create site.crt site.crt
    
    $ docker secret create site.conf site.conf
    
    $ docker secret ls
    
    ID                          NAME                  CREATED             UPDATED
    2hvoi9mnnaof7olr3z5g3g7fp   site.key       58 seconds ago      58 seconds ago
    aya1dh363719pkiuoldpter4b   site.crt       24 seconds ago      24 seconds ago
    zoa5df26f7vpcoz42qf2csth8   site.conf      11 seconds ago      11 seconds ago
    
  3. Créez un service qui exécute Nginx et a accès aux trois secrets. La dernière partie de la commande docker service create crée un lien symbolique à partir de l'emplacement du secret site.conf secret à /etc/nginx.conf.d/, où Nginx recherche des fichiers de configuration supplémentaires. Cette étape se produit avant que Nginx commence réellement, donc vous n'avez pas besoin de reconstruire votre image si vous changez la configuration Nginx.

    Note

    Normalement, vous créeriez une image Dockerfile qui copie le site.conf en place, construisez l'image, et exécutez un conteneur en utilisant votre image personnalisée. Cet exemple ne nécessite pas d'image personnalisée. Il place le site.conf en place et exécute le conteneur en une seule étape.

    Les secrets sont situés dans le répertoire /run/secrets/ dans le conteneur par défaut, ce qui peut nécessiter des étapes supplémentaires dans le conteneur pour rendre le secret disponible à un autre chemin. L'exemple ci-dessous crée un lien symbolique au vrai emplacement du fichier site.conf pour que Nginx puisse le lire :

    $ docker service create \
         --name nginx \
         --secret site.key \
         --secret site.crt \
         --secret site.conf \
         --publish published=3000,target=443 \
         nginx:latest \
         sh -c "ln -s /run/secrets/site.conf /etc/nginx/conf.d/site.conf && exec nginx -g 'daemon off;'"
    

    Au lieu de créer des liens symboliques, les secrets vous permettent de spécifier un emplacement personnalisé en utilisant l'option target. L'exemple ci-dessous illustre comment le secret site.conf est rendu disponible à /etc/nginx/conf.d/site.conf à l'intérieur du conteneur sans l'utilisation de liens symboliques :

    $ docker service create \
         --name nginx \
         --secret site.key \
         --secret site.crt \
         --secret source=site.conf,target=/etc/nginx/conf.d/site.conf \
         --publish published=3000,target=443 \
         nginx:latest \
         sh -c "exec nginx -g 'daemon off;'"
    

    Les secrets site.key et site.crt utilisent la syntaxe courte, sans emplacement personnalisé défini. La syntaxe courte monte les secrets dans `/run/secrets/ avec le même nom que le secret. À l'intérieur des conteneurs en cours d'exécution, les trois fichiers suivants existent maintenant :

    • /run/secrets/site.key
    • /run/secrets/site.crt
    • /etc/nginx/conf.d/site.conf
  4. Vérifiez que le service Nginx est en cours d'exécution.

    $ docker service ls
    
    ID            NAME   MODE        REPLICAS  IMAGE
    zeskcec62q24  nginx  replicated  1/1       nginx:latest
    
    $ docker service ps nginx
    
    NAME                  IMAGE         NODE  DESIRED STATE  CURRENT STATE          ERROR  PORTS
    nginx.1.9ls3yo9ugcls  nginx:latest  moby  Running        Running 3 minutes ago
    
  5. Vérifiez que le service est opérationnel : vous pouvez accéder au serveur Nginx, et que le certificat TLS correct est utilisé.

    $ curl --cacert root-ca.crt https://localhost:3000
    
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
            width: 35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support. refer to
    <a href="https://nginx.org">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="https://www.nginx.com">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    
    $ openssl s_client -connect localhost:3000 -CAfile root-ca.crt
    
    CONNECTED(00000003)
    depth=1 /C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA
    verify return:1
    depth=0 /C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost
    verify return:1
    ---
    Certificate chain
     0 s:/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost
       i:/C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA
    ---
    Server certificate
    -----BEGIN CERTIFICATE-----
    -----END CERTIFICATE-----
    subject=/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost
    issuer=/C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA
    ---
    No client certificate CA names sent
    ---
    SSL handshake has read 1663 bytes and written 712 bytes
    ---
    New, TLSv1/SSLv3, Cipher is AES256-SHA
    Server public key is 4096 bit
    Secure Renegotiation IS supported
    Compression: NONE
    Expansion: NONE
    SSL-Session:
        Protocol  : TLSv1
        Cipher    : AES256-SHA
        Session-ID: A1A8BF35549C5715648A12FD7B7E3D861539316B03440187D9DA6C2E48822853
        Session-ID-ctx:
        Master-Key: F39D1B12274BA16D3A906F390A61438221E381952E9E1E05D3DD784F0135FB81353DA38C6D5C021CB926E844DFC49FC4
        Key-Arg   : None
        Start Time: 1481685096
        Timeout   : 300 (sec)
        Verify return code: 0 (ok)
    
  6. Pour nettoyer après avoir exécuté cet exemple, supprimez le service nginx et les secrets stockés.

    $ docker service rm nginx
    
    $ docker secret rm site.crt site.key site.conf
    

Exemple avancé : Utiliser les secrets avec un service WordPress

Dans cet exemple, vous créez un service MySQL unique avec un mot de passe racine personnalisé, ajoutez les identifiants comme secrets, et créez un service WordPress unique qui utilise ces identifiants pour se connecter à MySQL. L'exemple suivant construit sur celui-ci et vous montre comment tourner le mot de passe MySQL et mettre à jour les services pour que le service WordPress puisse toujours se connecter à MySQL.

Cet exemple illustre certaines techniques pour utiliser Docker secrets pour éviter de stocker des identifiants sensibles dans votre image ou de les passer directement en ligne de commande.

Note

Cet exemple utilise un swarm à moteur unique pour la simplicité, et utilise un service MySQL unique car un seul serveur MySQL ne peut être mis à l'échelle simplement en utilisant un service répliqué, et la mise en place d'un cluster MySQL est au-delà de la portée de cet exemple.

De plus, changer le mot de passe racine MySQL n'est pas aussi simple que changer une variable d'environnement ou un fichier sur le disque. Vous devez utiliser une requête ou une commande mysqladmin pour changer le mot de passe dans MySQL.

  1. Générez un mot de passe alphanumérique aléatoire pour MySQL et stockez-le comme secret Docker avec le nom mysql_password en utilisant la commande docker secret create. Pour rendre le mot de passe plus court ou plus long, ajustez le dernier argument de la commande openssl. C'est juste une façon de créer un mot de passe relativement aléatoire. Vous pouvez utiliser une autre commande pour générer le mot de passe si vous le souhaitez.

    Le dernier argument est défini à -, ce qui indique que l'entrée est lue de standard.

    $ openssl rand -base64 20 | docker secret create mysql_password -
    
    l1vinzevzhj4goakjap5ya409
    

    La valeur renvoyée n'est pas le mot de passe, mais l'ID du secret. Dans le reste de ce tutoriel, l'ID de sortie est omis.

    Générez un second secret pour le root MySQL. Ce secret n'est pas partagé avec le service WordPress créé plus tard. Il est uniquement nécessaire pour démarrer le mysql service.

    $ openssl rand -base64 20 | docker secret create mysql_root_password -
    

    Listez les secrets gérés par Docker en utilisant docker secret ls :

    $ docker secret ls
    
    ID                          NAME                  CREATED             UPDATED
    l1vinzevzhj4goakjap5ya409   mysql_password        41 seconds ago      41 seconds ago
    yvsczlx9votfw3l0nz5rlidig   mysql_root_password   12 seconds ago      12 seconds ago
    

    Les secrets sont stockés dans les journaux Raft chiffrés pour le swarm.

  2. Créez un réseau de superposition utilisé pour la communication entre le MySQL et le service WordPress. Il n'est pas nécessaire d'exposer le service MySQL à tout hôte ou conteneur externe.

    $ docker network create -d overlay mysql_private
    
  3. Créez le service MySQL. Le service MySQL a les caractéristiques suivantes :

    • Parce que l'échelle est définie sur 1, seule une tâche MySQL unique s'exécute. Équilibrer la charge MySQL est laissé en exercice au lecteur et implique plus que simplement mettre à l'échelle le service.

    • Seulement accessible par d'autres conteneurs sur le réseau mysql_private.

    • Utilise le volume mydata pour stocker les données MySQL, de sorte qu'elles persistent au-delà des redémarrages à la mysql service.

    • Les secrets sont chacun montés dans un système de fichiers tmpfs à /run/secrets/mysql_password et /run/secrets/mysql_root_password. Ils ne sont jamais exposés comme variables d'environnement, ni peut-être commité à une image si la commande docker commit est exécutée. Le secret mysql_password est celui utilisé par le conteneur WordPress non privilégié pour se connecter à MySQL.

    • Définit les variables d'environnement MYSQL_PASSWORD_FILE et MYSQL_ROOT_PASSWORD_FILE pour pointer vers les fichiers /run/secrets/mysql_password et /run/secrets/mysql_root_password. L'image mysql lit les chaînes de mot de passe de ces fichiers lors de l'initialisation du système de base de données pour la première fois. Après cela, les mots de passe sont stockés dans la base de données système MySQL elle-même.

    • Définit les variables d'environnement MYSQL_USER et MYSQL_DATABASE. Une nouvelle base de données appelée wordpress est créée lorsque le conteneur démarre, et le wordpress utilisateur a des permissions totales pour cette base de données uniquement. Ce utilisateur ne peut pas créer ou supprimer des bases de données ou modifier la configuration MySQL.

      $ docker service create \
           --name mysql \
           --replicas 1 \
           --network mysql_private \
           --mount type=volume,source=mydata,destination=/var/lib/mysql \
           --secret source=mysql_root_password,target=mysql_root_password \
           --secret source=mysql_password,target=mysql_password \
           -e MYSQL_ROOT_PASSWORD_FILE="/run/secrets/mysql_root_password" \
           -e MYSQL_PASSWORD_FILE="/run/secrets/mysql_password" \
           -e MYSQL_USER="wordpress" \
           -e MYSQL_DATABASE="wordpress" \
           mysql:latest
      
  4. Vérifiez que le conteneur mysql est en cours d'exécution en utilisant la commande docker service ls.

    $ docker service ls
    
    ID            NAME   MODE        REPLICAS  IMAGE
    wvnh0siktqr3  mysql  replicated  1/1       mysql:latest
    
  5. Maintenant que MySQL est configuré, créez un service WordPress qui se connecte au service MySQL. Le service WordPress a les caractéristiques suivantes :

    • Parce que l'échelle est définie sur 1, seule une tâche WordPress unique s'exécute. Équilibrer la charge WordPress est laissé en exercice au lecteur, car de limitations avec stocker les données WordPress sur le système de fichiers du conteneur .
    • Expose WordPress sur le port 30000 de la machine hôte, de sorte que vous puissiez accéder à partir d'hôtes externes. Vous pouvez exposer le port 80 à la place si vous n'avez pas de serveur web en cours d'exécution sur le port 80 de la machine hôte.
    • Se connecte au réseau mysql_private pour qu'il puisse communiquer avec le mysql conteneur, et publie également le port 80 sur tous les nœuds swarm.
    • A accès au secret mysql_password, mais spécifie un nom de fichier différent à l'intérieur du conteneur. Le conteneur WordPress utilise le point de montage /run/secrets/wp_db_password.
    • Définit la variable d'environnement WORDPRESS_DB_PASSWORD_FILE au chemin du fichier où le secret est monté. Le service WordPress lit la chaîne de mot de passe MySQL de ce fichier et la ajoute au fichier de configuration wp-config.php .
    • Se connecte au conteneur MySQL en utilisant le nom d'utilisateur wordpress et le mot de passe dans /run/secrets/wp_db_password et crée le wordpress base de données si elle n'existe pas encore.
    • Stocke ses données, telles que les thèmes et les plugins, dans un volume appelé wpdata pour que ces fichiers persistent lorsque le service redémarre.
    $ docker service create \
         --name wordpress \
         --replicas 1 \
         --network mysql_private \
         --publish published=30000,target=80 \
         --mount type=volume,source=wpdata,destination=/var/www/html \
         --secret source=mysql_password,target=wp_db_password \
         -e WORDPRESS_DB_USER="wordpress" \
         -e WORDPRESS_DB_PASSWORD_FILE="/run/secrets/wp_db_password" \
         -e WORDPRESS_DB_HOST="mysql:3306" \
         -e WORDPRESS_DB_NAME="wordpress" \
         wordpress:latest
    
  6. Vérifiez le service en cours d'exécution en utilisant les commandes docker service ls et docker service ps.

    $ docker service ls
    
    ID            NAME       MODE        REPLICAS  IMAGE
    wvnh0siktqr3  mysql      replicated  1/1       mysql:latest
    nzt5xzae4n62  wordpress  replicated  1/1       wordpress:latest
    
    $ docker service ps wordpress
    
    ID            NAME         IMAGE             NODE  DESIRED STATE  CURRENT STATE           ERROR  PORTS
    aukx6hgs9gwc  wordpress.1  wordpress:latest  moby  Running        Running 52 seconds ago   
    

    À ce stade, vous pourriez en fait révoquer l'accès du service WordPress au secret mysql_password, car WordPress a copié le secret dans son fichier de configuration wp-config.php. Ne le faites pas pour le moment, car nous l'utilisons plus tard pour faciliter la rotation du mot de passe MySQL.

  7. Accédez à http://localhost:30000/ à partir de n'importe quel nœud swarm et configurez WordPress en utilisant le wizard web. Tous ces paramètres sont stockés dans la base de données MySQL wordpress. WordPress génère automatiquement un mot de passe pour votre utilisateur WordPress, qui est complètement différent de celui que WordPress utilise pour accéder à MySQL. Stockez ce mot de passe en toute sécurité, comme dans un gestionnaire de mot de passe. Vous en avez besoin pour vous connecter à WordPress après faire tourner le secret.

    Allez-y et écrivez un article ou deux et installez un plugin ou thème WordPress pour vérifier que WordPress est pleinement opérationnel et son état est sauvegardé au-delà des redémarrages de service.

  8. Ne nettoyez aucun service ou secret si vous souhaitez passer à l'exemple suivant, qui montre comment tourner le mot de passe racine MySQL.

Exemple : Faire tourner un secret

Cet exemple construit sur le précédent. Dans ce scénario, vous créez un nouveau secret avec un nouveau mot de passe MySQL, mettez à jour les services mysql et wordpress pour en utiliser, puis supprimez l'ancien secret.

Note

Changer le mot de passe sur une base de données MySQL implique l'exécution de requêtes supplémentaires ou de commandes, contrairement à simplement changer une variable d'environnement ou un fichier, car l'image ne définit le mot de passe MySQL que si la base de données n'existe pas déjà, et MySQL stocke le mot de passe dans la base de données MySQL par défaut. Roter les mots de passe ou d'autres secrets peut impliquer des étapes supplémentaires en dehors de Docker.

  1. Créez le nouveau mot de passe et stockez-le comme secret nommé mysql_password_v2.

    $ openssl rand -base64 20 | docker secret create mysql_password_v2 -
    
  2. Mettez à jour le service MySQL pour lui accorder accès aux secrets anciens et nouveaux. Rappelez-vous que vous ne pouvez pas mettre à jour ou renommer un secret, mais vous pouvez révoquer un secret et accorder accès à lui en utilisant un nouveau nom de fichier cible.

    $ docker service update \
         --secret-rm mysql_password mysql
    
    $ docker service update \
         --secret-add source=mysql_password,target=old_mysql_password \
         --secret-add source=mysql_password_v2,target=mysql_password \
         mysql
    

    Mettre à jour un service provoque son redémarrage, et lorsque le service MySQL redémarre la deuxième fois, il a accès aux secrets anciens sous /run/secrets/old_mysql_password et aux secrets nouveaux sous /run/secrets/mysql_password.

    Même si le service MySQL a accès aux secrets anciens et nouveaux maintenant, le mot de passe MySQL pour l'utilisateur wordpress n'a pas encore été changé.

    Note

    Cet exemple ne fait pas tourner le mot de passe MySQL root.

  3. Maintenant, changez le mot de passe MySQL pour l'utilisateur wordpress en utilisant la CLI mysqladmin. Cette commande lit les anciens et nouveaux mots de passe des fichiers dans /run/secrets mais ne les expose pas en ligne de commande ou enregistre dans l'historique de la console.

    Faites cela rapidement et passez à l'étape suivante, car WordPress perd la capacité de se connecter à MySQL.

    Premièrement, trouvez l'ID du conteneur de tâche mysql.

    $ docker ps --filter name=mysql -q
    
    c7705cf6176f
    

    Substituez l'ID dans la commande ci-dessous, ou utilisez la seconde variante qui fait tout en une seule étape.

    $ docker container exec <CONTAINER_ID> \
        bash -c 'mysqladmin --user=wordpress --password="$(< /run/secrets/old_mysql_password)" password "$(< /run/secrets/mysql_password)"'
    

    Ou:

    $ docker container exec $(docker ps --filter name=mysql -q) \
        bash -c 'mysqladmin --user=wordpress --password="$(< /run/secrets/old_mysql_password)" password "$(< /run/secrets/mysql_password)"'
    
  4. Mettez à jour le service wordpress pour utiliser le nouveau mot de passe, en gardant le chemin cible à /run/secrets/wp_db_password. Cela déclenche un redémarrage roulant du service et le nouveau secret est utilisé.

    $ docker service update \
         --secret-rm mysql_password \
         --secret-add source=mysql_password_v2,target=wp_db_password \
         wordpress    
    
  5. Vérifiez que WordPress fonctionne en parcourant http://localhost:30000/ sur n'importe quel nœud swarm à nouveau. Utilisez le nom d'utilisateur et le mot de passe de lorsque vous avez suivi le wizard WordPress dans la tâche précédente.

    Vérifiez que le billet que vous avez écrit existe toujours, et si vous avez changé des valeurs de configuration, vérifiez qu'elles sont toujours changées.

  6. Révoquez l'accès à l'ancien secret du service MySQL et supprimez l'ancien secret de Docker.

    $ docker service update \
         --secret-rm mysql_password \
         mysql
    
    $ docker secret rm mysql_password
    
  7. Exécutez les commandes suivantes pour supprimer le service WordPress, le conteneur MySQL, les volumes mydata et wpdata, et les secrets Docker :

    $ docker service rm wordpress mysql
    
    $ docker volume rm mydata wpdata
    
    $ docker secret rm mysql_password_v2 mysql_root_password
    

Intégrer le support des secrets Docker dans vos images

Si vous développez un conteneur qui peut être déployé comme un service et nécessite un identifiant sensible, comme un identifiant, considérez adapter votre image pour tirer parti des secrets Docker. Une façon de le faire est de s'assurer que chaque paramètre que vous passez à l'image lors de la création du conteneur peut également être lu d'un fichier.

De nombreuses images officielles Docker dans le Docker library, telles que l' image wordpress utilisée dans les exemples ci-dessus, ont été mises à jour de cette manière.

Lorsque vous démarrez un conteneur WordPress, vous lui fournissez les paramètres dont il a besoin en les définissant comme variables d'environnement. L'image WordPress a été mise à jour pour que les variables d'environnement qui contiennent des informations importantes pour WordPress, telles que WORDPRESS_DB_PASSWORD, aient également des variantes qui peuvent lire leurs valeurs de fichier (WORDPRESS_DB_PASSWORD_FILE). Cette stratégie garantit la compatibilité vers l'arrière, tout en permettant à votre conteneur de lire les informations de Docker-managed secret à la place d'être passé directement.

Note

Docker secrets ne définissent pas directement les variables d'environnement. C'était une décision consciente, car les variables d'environnement peuvent s'échapper entre conteneurs (par exemple, si vous utilisez --link).

Utiliser les secrets dans Compose


services:
   db:
     image: mysql:latest
     volumes:
       - db_data:/var/lib/mysql
     environment:
       MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD_FILE: /run/secrets/db_password
     secrets:
       - db_root_password
       - db_password

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password
     secrets:
       - db_password


secrets:
   db_password:
     file: db_password.txt
   db_root_password:
     file: db_root_password.txt

volumes:
    db_data:

Cet exemple crée un simple site WordPress utilisant deux secrets dans un fichier Compose.

L'élément de niveau supérieur secrets définit deux secrets db_password et db_root_password.

Lors du déploiement, Docker crée ces deux secrets et les remplit avec le contenu du fichier spécifié dans le fichier Compose.

Le service db utilise les deux secrets, et wordpress n'utilise qu'un.

Lorsque vous déployez, Docker monte un fichier sous /run/secrets/<secret_name> dans les services. Ces fichiers ne sont jamais persistés sur disque, mais sont gérés en mémoire.

Chaque service utilise des variables d'environnement pour spécifier où le service devrait chercher ces données secrètes.

Plus d'informations sur la syntaxe courte et longue pour les secrets peuvent être trouvées dans la Spécification Compose.