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

Liens de conteneurs hérités

Warning

Le drapeau --link est une fonctionnalité héritée de Docker. Il pourrait éventuellement être supprimé. Sauf si vous avez absolument besoin de continuer à l'utiliser, nous recommandons d'utiliser des réseaux définis par l'utilisateur pour faciliter la communication entre deux conteneurs au lieu d'utiliser --link. Une fonctionnalité que les réseaux définis par l'utilisateur ne prennent pas en charge que vous pouvez faire avec --link est le partage de variables d'environnement entre conteneurs. Cependant, vous pouvez utiliser d'autres mécanismes tels que les volumes pour partager des variables d'environnement entre conteneurs de manière plus contrôlée.

Voir Différences entre les bridges définis par l'utilisateur et le bridge par défaut pour quelques alternatives à l'utilisation de --link.

Les informations de cette section expliquent les liens de conteneurs hérités dans le réseau bridge par défaut de Docker qui est créé automatiquement lorsque vous installez Docker.

Avant la fonctionnalité réseaux Docker, vous pouviez utiliser la fonctionnalité de lien Docker pour permettre aux conteneurs de se découvrir et transférer de manière sécurisée des informations d'un conteneur à un autre conteneur. Avec l' introduction de la fonctionnalité réseaux Docker, vous pouvez toujours créer des liens mais ils se comportent différemment entre le réseau bridge par défaut et les réseaux définis par l'utilisateur.

Cette section discute brièvement de la connexion via un port réseau puis entre dans le détail sur la liaison de conteneurs dans le réseau bridge par défaut.

Se connecter en utilisant le mappage de port réseau

Disons que vous avez utilisé cette commande pour exécuter une simple application Python Flask :

$ docker run -d -P training/webapp python app.py
Note

Les conteneurs ont un réseau interne et une adresse IP. Docker peut avoir une variété de configurations réseau. Vous pouvez voir plus d'informations sur les réseaux Docker ici.

Quand ce conteneur a été créé, le drapeau -P a été utilisé pour mapper automatiquement tout port réseau à l'intérieur vers un port élevé aléatoire dans une plage de ports éphémères sur votre hôte Docker. Ensuite, quand docker ps a été exécuté, vous avez vu que le port 5000 dans le conteneur était lié au port 49155 sur l'hôte.

$ docker ps nostalgic_morse

CONTAINER ID  IMAGE                   COMMAND       CREATED        STATUS        PORTS                    NAMES
bc533791f3f5  training/webapp:latest  python app.py 5 seconds ago  Up 2 seconds  0.0.0.0:49155->5000/tcp  nostalgic_morse

Vous avez aussi vu comment vous pouvez lier les ports d'un conteneur à un port spécifique en utilisant le drapeau -p. Ici le port 80 de l'hôte est mappé au port 5000 du conteneur :

$ docker run -d -p 80:5000 training/webapp python app.py

Et vous avez vu pourquoi ce n'est pas une si bonne idée car cela vous contraint à un seul conteneur sur ce port spécifique.

Au lieu de cela, vous pouvez spécifier une plage de ports d'hôte pour lier un port de conteneur à qui est différente de la plage de ports éphémères par défaut :

$ docker run -d -p 8000-9000:5000 training/webapp python app.py

Cela lierait le port 5000 dans le conteneur à un port disponible aléatoirement entre 8000 et 9000 sur l'hôte.

Il y a aussi quelques autres façons de configurer le drapeau -p. Par défaut le drapeau -p lie le port spécifié à toutes les interfaces sur la machine hôte. Mais vous pouvez aussi spécifier une liaison à une interface spécifique, par exemple seulement au localhost.

$ docker run -d -p 127.0.0.1:80:5000 training/webapp python app.py

Cela lierait le port 5000 à l'intérieur du conteneur au port 80 sur l' interface localhost ou 127.0.0.1 sur la machine hôte.

Ou, pour lier le port 5000 du conteneur à un port dynamique mais seulement sur le localhost, vous pourriez utiliser :

$ docker run -d -p 127.0.0.1::5000 training/webapp python app.py

Vous pouvez aussi lier les ports UDP et SCTP (typiquement utilisés par des protocoles télécom tels que SIGTRAN, Diameter, et S1AP/X2AP) en ajoutant un /udp ou /sctp final. Par exemple :

$ docker run -d -p 127.0.0.1:80:5000/udp training/webapp python app.py

Vous avez aussi appris le raccourci utile docker port qui nous a montré les liaisons de port actuelles. C'est aussi utile pour montrer des configurations de port spécifiques. Par exemple, si vous avez lié le port du conteneur au localhost sur la machine hôte, alors la sortie docker port reflète cela.

$ docker port nostalgic_morse 5000

127.0.0.1:49155
Note

Le drapeau -p peut être utilisé plusieurs fois pour configurer plusieurs ports.

Se connecter avec le système de liaison

Note

Cette section couvre la fonctionnalité de lien héritée dans le réseau bridge par défaut. Référez-vous aux différences entre les bridges définis par l'utilisateur et le bridge par défaut pour plus d'informations sur les liens dans les réseaux définis par l'utilisateur.

Les mappages de port réseau ne sont pas la seule façon dont les conteneurs Docker peuvent se connecter les uns aux autres. Docker a aussi un système de liaison qui permet de lier plusieurs conteneurs ensemble et d'envoyer des informations de connexion de l'un à l'autre. Quand les conteneurs sont liés, des informations sur un conteneur source peuvent être envoyées à un conteneur destinataire. Cela permet au destinataire de voir des données sélectionnées décrivant les aspects du conteneur source.

L'importance du nommage

Pour établir des liens, Docker s'appuie sur les noms de vos conteneurs. Vous avez déjà vu que chaque conteneur que vous créez a un nom automatiquement créé ; en effet vous êtes devenu familier avec notre vieil ami nostalgic_morse pendant ce guide. Vous pouvez aussi nommer les conteneurs vous-même. Ce nommage fournit deux fonctions utiles :

  1. Il peut être utile de nommer les conteneurs qui font des fonctions spécifiques d'une manière qui facilite leur mémorisation, par exemple nommer un conteneur contenant une application web web.

  2. Il fournit à Docker un point de référence qui lui permet de se référer à d'autres conteneurs, par exemple, vous pouvez spécifier de lier le conteneur web au conteneur db.

Vous pouvez nommer votre conteneur en utilisant le drapeau --name, par exemple :

$ docker run -d -P --name web training/webapp python app.py

Cela lance un nouveau conteneur et utilise le drapeau --name pour nommer le conteneur web. Vous pouvez voir le nom du conteneur en utilisant la commande docker ps.

$ docker ps -l

CONTAINER ID  IMAGE                  COMMAND        CREATED       STATUS       PORTS                    NAMES
aed84ee21bde  training/webapp:latest python app.py  12 hours ago  Up 2 seconds 0.0.0.0:49154->5000/tcp  web

Vous pouvez aussi utiliser docker inspect pour retourner le nom du conteneur.

Note

Les noms de conteneurs doivent être uniques. Cela signifie que vous ne pouvez appeler qu'un seul conteneur web. Si vous voulez réutiliser un nom de conteneur vous devez supprimer l'ancien conteneur (avec docker container rm) avant de pouvoir créer un nouveau conteneur avec le même nom. Comme alternative vous pouvez utiliser le drapeau --rm avec la commande docker run. Cela supprime le conteneur immédiatement après qu'il soit arrêté.

Communication à travers les liens

Les liens permettent aux conteneurs de se découvrir et de transférer de manière sécurisée des informations d'un conteneur à un autre conteneur. Quand vous établissez un lien, vous créez un conduit entre un conteneur source et un conteneur destinataire. Le destinataire peut alors accéder à des données sélectionnées sur la source. Pour créer un lien, vous utilisez le drapeau --link. D'abord, créez un nouveau conteneur, cette fois un contenant une base de données.

$ docker run -d --name db training/postgres

Cela crée un nouveau conteneur appelé db à partir de l'image training/postgres, qui contient une base de données PostgreSQL.

Maintenant, vous devez supprimer le conteneur web que vous avez créé précédemment pour pouvoir le remplacer par un lié :

$ docker container rm -f web

Maintenant, créez un nouveau conteneur web et liez-le avec votre conteneur db.

$ docker run -d -P --name web --link db:db training/webapp python app.py

Cela lie le nouveau conteneur web avec le conteneur db que vous avez créé plus tôt. Le drapeau --link prend la forme :

--link <name or id>:alias

name est le nom du conteneur que nous lions et alias est un alias pour le nom du lien. Cet alias est utilisé bientôt. Le drapeau --link prend aussi la forme :

--link <name or id>

Dans ce cas l'alias correspond au nom. Vous pourriez écrire l'exemple précédent comme :

$ docker run -d -P --name web --link db training/webapp python app.py

Ensuite, inspectez vos conteneurs liés avec docker inspect :

$ docker inspect -f "{{ .HostConfig.Links }}" web

[/db:/web/db]

Vous pouvez voir que le conteneur web est maintenant lié au conteneur db web/db. Ce qui lui permet d'accéder aux informations sur le conteneur db.

Alors que fait réellement la liaison des conteneurs ? Vous avez appris qu'un lien permet à un conteneur source de fournir des informations sur lui-même à un conteneur destinataire. Dans notre exemple, le destinataire, web, peut accéder aux informations sur la source db. Pour faire cela, Docker crée un tunnel sécurisé entre les conteneurs qui n'a pas besoin d'exposer de ports en externe sur le conteneur ; quand nous avons démarré le conteneur db nous n'avons utilisé ni le drapeau -P ni -p. C'est un gros avantage de la liaison : nous n'avons pas besoin d'exposer le conteneur source, ici la base de données PostgreSQL, au réseau.

Docker expose les informations de connectivité pour le conteneur source au conteneur destinataire de deux façons :

  • Variables d'environnement,
  • Mise à jour du fichier /etc/hosts.

Variables d'environnement

Docker crée plusieurs variables d'environnement quand vous liez des conteneurs. Docker crée automatiquement des variables d'environnement dans le conteneur cible basées sur les paramètres --link. Il expose aussi toutes les variables d'environnement provenant de Docker du conteneur source. Celles-ci incluent les variables de :

  • les commandes ENV dans le Dockerfile du conteneur source
  • les options -e, --env, et --env-file sur la commande docker run quand le conteneur source est démarré

Ces variables d'environnement permettent la découverte programmatique depuis le conteneur cible d'informations liées au conteneur source.

Warning

Il est important de comprendre que toutes les variables d'environnement provenant de Docker dans un conteneur sont rendues disponibles à tout conteneur qui lui est lié. Cela pourrait avoir de sérieuses implications de sécurité si des données sensibles sont stockées dedans.

Docker définit une variable d'environnement <alias>_NAME pour chaque conteneur cible listé dans le paramètre --link. Par exemple, si un nouveau conteneur appelé web est lié à un conteneur de base de données appelé db via --link db:webdb, alors Docker crée une variable WEBDB_NAME=/web/webdb dans le conteneur web.

Docker définit aussi un ensemble de variables d'environnement pour chaque port exposé par le conteneur source. Chaque variable a un préfixe unique de la forme <n>_PORT_<port>_<protocol>

Les composants dans ce préfixe sont :

  • l'alias <n> spécifié dans le paramètre --link (par exemple, webdb)
  • le numéro de <port> exposé
  • un <protocol> qui est soit TCP soit UDP

Docker utilise ce format de préfixe pour définir trois variables d'environnement distinctes :

  • La variable prefix_ADDR contient l'adresse IP de l'URL, par exemple WEBDB_PORT_5432_TCP_ADDR=172.17.0.82.
  • La variable prefix_PORT contient juste le numéro de port de l'URL par exemple WEBDB_PORT_5432_TCP_PORT=5432.
  • La variable prefix_PROTO contient juste le protocole de l'URL par exemple WEBDB_PORT_5432_TCP_PROTO=tcp.

Si le conteneur expose plusieurs ports, un ensemble de variables d'environnement est défini pour chacun. Cela signifie, par exemple, si un conteneur expose 4 ports que Docker crée 12 variables d'environnement, 3 pour chaque port.

De plus, Docker crée une variable d'environnement appelée <alias>_PORT. Cette variable contient l'URL du premier port exposé du conteneur source. Le 'premier' port est défini comme le port exposé avec le numéro le plus bas. Par exemple, considérez la variable WEBDB_PORT=tcp://172.17.0.82:5432. Si ce port est utilisé pour tcp et udp, alors celui tcp est spécifié.

Finalement, Docker expose aussi chaque variable d'environnement provenant de Docker du conteneur source comme une variable d'environnement dans la cible. Pour chaque variable Docker crée une variable <alias>_ENV_<n> dans le conteneur cible. La valeur de la variable est définie à la valeur que Docker a utilisée quand il a démarré le conteneur source.

Revenant à notre exemple de base de données, vous pouvez exécuter la commande env pour lister les variables d'environnement du conteneur spécifié.

$ docker run --rm --name web2 --link db:db training/webapp env

<...>
DB_NAME=/web2/db
DB_PORT=tcp://172.17.0.5:5432
DB_PORT_5432_TCP=tcp://172.17.0.5:5432
DB_PORT_5432_TCP_PROTO=tcp
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_ADDR=172.17.0.5
<...>

Vous pouvez voir que Docker a créé une série de variables d'environnement avec des informations utiles sur le conteneur source db. Chaque variable est préfixée avec DB_, qui est rempli à partir de l'alias que vous avez spécifié ci-dessus. Si l'alias était db1, les variables seraient préfixées avec DB1_. Vous pouvez utiliser ces variables d'environnement pour configurer vos applications pour se connecter à la base de données sur le conteneur db. La connexion est sécurisée et privée ; seul le conteneur web lié peut communiquer avec le conteneur db.

Notes importantes sur les variables d'environnement Docker

Contrairement aux entrées d'hôte dans le fichier /etc/hosts, les adresses IP stockées dans les variables d'environnement ne sont pas automatiquement mises à jour si le conteneur source est redémarré. Nous recommandons d'utiliser les entrées d'hôte dans /etc/hosts pour résoudre l'adresse IP des conteneurs liés.

Ces variables d'environnement ne sont définies que pour le premier processus dans le conteneur. Certains démons, comme sshd, les nettoient quand ils génèrent des shells pour la connexion.

Mise à jour du fichier /etc/hosts

En plus des variables d'environnement, Docker ajoute une entrée d'hôte pour le conteneur source au fichier /etc/hosts. Voici une entrée pour le conteneur web :

$ docker run -t -i --rm --link db:webdb training/webapp /bin/bash

root@aed84ee21bde:/opt/webapp# cat /etc/hosts
172.17.0.7  aed84ee21bde
<...>
172.17.0.5  webdb 6e5cdeb2d300 db

Vous pouvez voir deux entrées d'hôte pertinentes. La première est une entrée pour le conteneur web qui utilise l'ID du conteneur comme nom d'hôte. La deuxième entrée utilise l' alias du lien pour référencer l'adresse IP du conteneur db. En plus de l'alias que vous fournissez, le nom du conteneur lié, s'il est unique de l'alias fourni au paramètre --link, et le nom d'hôte du conteneur lié sont aussi ajoutés à /etc/hosts pour l'adresse IP du conteneur lié. Vous pouvez ping cet hôte via n'importe laquelle de ces entrées :

root@aed84ee21bde:/opt/webapp# apt-get install -yqq inetutils-ping
root@aed84ee21bde:/opt/webapp# ping webdb

PING webdb (172.17.0.5): 48 data bytes
56 bytes from 172.17.0.5: icmp_seq=0 ttl=64 time=0.267 ms
56 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.250 ms
56 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.256 ms
Note

Dans l'exemple, vous avez dû installer ping car il n'était pas inclus dans le conteneur initialement.

Ici, vous avez utilisé la commande ping pour ping le conteneur db en utilisant son entrée d'hôte, qui se résout à 172.17.0.5. Vous pouvez utiliser cette entrée d'hôte pour configurer une application pour faire usage de votre conteneur db.

Note

Vous pouvez lier plusieurs conteneurs destinataires à une seule source. Par exemple, vous pourriez avoir plusieurs conteneurs web (nommés différemment) attachés à votre conteneur db.

Si vous redémarrez le conteneur source, les fichiers /etc/hosts sur les conteneurs liés sont automatiquement mis à jour avec la nouvelle adresse IP du conteneur source, permettant à la communication liée de continuer.

$ docker restart db
db

$ docker run -t -i --rm --link db:db training/webapp /bin/bash

root@aed84ee21bde:/opt/webapp# cat /etc/hosts
172.17.0.7  aed84ee21bde
<...>
172.17.0.9  db