Comment communiquer entre les conteneurs Docker via «hostname»

Je prévois de diviser mon serveur monolthique en plusieurs petits conteneurs Docker, mais je n’ai pas encore trouvé de solution pour la “communication entre conteneurs”. Ceci est mon scénario cible:

Scénario cible

Je sais comment relier les conteneurs entre eux et comment exposer les ports, mais aucune de ces solutions ne me satisfait.

Existe-t-il une solution pour communiquer via des noms d’hôte (noms de conteneur) entre les conteneurs, comme sur un réseau de serveurs traditionnel?

Edit: Après Docker 1.9, la commande docker network (voir ci-dessous https://stackoverflow.com/a/35184695/977939 ) est la méthode recommandée pour y parvenir.


Ma solution consiste à configurer un serveur DNS sur l’hôte pour que l’enregistrement DNS soit automatiquement mis à jour: les enregistrements “A” portent les noms des conteneurs et indiquent automatiquement les adresses IP des conteneurs (toutes les 10 secondes). Le script de mise à jour automatique est collé ici:

 #!/bin/bash # 10 seconds interval time by default INTERVAL=${INTERVAL:-10} # dnsmasq config directory DNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.} # commands used in this script DOCKER=${DOCKER:-docker} SLEEP=${SLEEP:-sleep} TAIL=${TAIL:-tail} declare -A service_map while true do changed=false while read line do name=${line##* } ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name) if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed then service_map[$name]=$ip # write to file echo $name has a new IP Address $ip >&2 echo "host-record=$name,$ip" > "${DNSMASQ_CONFIG}/docker-$name" changed=true fi done < <(${DOCKER} ps | ${TAIL} -n +2) # a change of IP address occured, restart dnsmasq if [ $changed = true ] then systemctl restart dnsmasq fi ${SLEEP} $INTERVAL done 

Assurez-vous que votre service dnsmasq est disponible sur docker0 . Ensuite, démarrez votre conteneur avec --dns HOST_ADDRESS pour utiliser ce service mini dns.

Référence: http://docs.blowb.org/setup-host/dnsmasq.html

La nouvelle fonctionnalité de mise en réseau vous permet de vous connecter aux conteneurs par leur nom. Par conséquent, si vous créez un nouveau réseau, tout conteneur connecté à ce réseau peut atteindre d’autres conteneurs par leur nom. Exemple:

1) Créer un nouveau réseau

 $ docker network create  

2) Connecter les conteneurs au réseau

 $ docker run --net= ... 

ou

 $ docker network connect   

3) Conteneur de ping par nom

 docker exec -ti  ping  64 bytes from c1 (172.18.0.4): icmp_seq=1 ttl=64 time=0.137 ms 64 bytes from c1 (172.18.0.4): icmp_seq=2 ttl=64 time=0.073 ms 64 bytes from c1 (172.18.0.4): icmp_seq=3 ttl=64 time=0.074 ms 64 bytes from c1 (172.18.0.4): icmp_seq=4 ttl=64 time=0.074 ms 

Voir cette section de la documentation

Remarque: contrairement aux links hérités, le nouveau réseau ne crée pas de variables d’environnement, ni ne partage de variables d’environnement avec d’autres conteneurs.

Cette fonctionnalité ne prend actuellement pas en charge les alias

Cela devrait être ce que --link est pour , au moins pour la partie hostname.
Avec docker 1.10 et PR 19242 , ce serait:

 docker network create --net-alias=[]: Add network-scoped alias for the container 

(voir dernière section ci-dessous)

C’est ce qui met à jour les détails du fichier /etc/hosts

Outre les variables d’environnement, Docker ajoute une entrée d’hôte pour le conteneur source au fichier /etc/hosts .

Par exemple, lancez un serveur LDAP:

 docker run -t --name openldap -d -p 389:389 larrycai/openldap 

Et définissez une image pour tester ce serveur LDAP:

 FROM ubuntu RUN apt-get -y install ldap-utils RUN touch /root/.bash_aliases RUN echo "alias lds='ldapsearch -H ldap://internalopenldap -LL -b ou=Users,dc=openstack,dc=org -D cn=admin,dc=openstack,dc=org -w password'" > /root/.bash_aliases ENTRYPOINT bash 

Vous pouvez exposer le conteneur ‘ openldap ‘ en tant que ‘ internalopenldap ‘ dans l’image de test avec –link:

  docker run -it --rm --name ldp --link openldap:internalopenldap ldaptest 

Ensuite, si vous tapez ‘lds’, cet alias fonctionnera:

 ldapsearch -H ldap://internalopenldap ... 

Cela rendrait les gens. La signification de internalopenldap est correctement atteinte à partir de l’image ldaptest .


Bien sûr, docker 1.7 appenda libnetwork , qui fournit une implémentation native de Go pour connecter des conteneurs. Voir l’ article de blog .
Il a introduit une architecture plus complète, avec le modèle de réseau de conteneurs (CNM)

https://blog.docker.com/media/2015/04/cnm-model.jpg

Cela mettra à jour l’interface de ligne de commande Docker avec de nouvelles commandes «réseau» et documentera comment l’ -net « -net » est utilisé pour atsortingbuer des conteneurs aux réseaux.


docker 1.10 a une nouvelle section Alias ​​de scope réseau , maintenant officiellement documenté dans network connect :

Alors que les liens fournissent une résolution de nom privé localisée dans un conteneur, l’alias de scope réseau permet à un conteneur d’être découvert par un autre nom par tout autre conteneur dans la scope d’un réseau particulier.
Contrairement à l’alias de lien, défini par le consommateur d’un service, l’alias de scope réseau est défini par le conteneur qui offre le service au réseau.

En poursuivant avec l’exemple ci-dessus, créez un autre conteneur dans isolated_nw avec un alias réseau.

 $ docker run --net=isolated_nw -itd --name=container6 -alias app busybox 8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17 --alias=[] 

Ajouter un alias de scope réseau pour le conteneur

Vous pouvez utiliser l’option --link pour lier un autre conteneur avec un alias préféré

Vous pouvez suspendre, redémarrer et arrêter les conteneurs connectés à un réseau. Les conteneurs en pause restnt connectés et peuvent être révélés par un réseau d’inspection. Lorsque le conteneur est arrêté, il n’apparaît pas sur le réseau tant que vous ne l’avez pas redémarré.

Si spécifié, les adresses IP du conteneur sont réappliquées lorsqu’un conteneur arrêté est redémarré. Si l’adresse IP n’est plus disponible, le conteneur ne démarre pas.

Un moyen de garantir la disponibilité de l’adresse IP consiste à spécifier un --ip-range lors de la création du réseau et à choisir l’adresse IP statique en dehors de cette plage. Cela garantit que l’adresse IP n’est pas donnée à un autre conteneur alors que ce conteneur n’est pas sur le réseau.

 $ docker network create --subnet 172.20.0.0/16 --ip-range 172.20.240.0/20 multi-host-network $ docker network connect --ip 172.20.128.2 multi-host-network container2 $ docker network connect --link container1:c1 multi-host-network container2 

EDIT : Il n’est plus à bout de souffle: http://blog.docker.com/2016/02/docker-1-10/

Réponse originale
Je me suis battu avec elle toute la nuit. Si vous ne craignez rien, la dernière version du moteur Docker et de Docker composent les deux implémentent libnetwork.

Avec le bon fichier de configuration (qui doit être mis en version 2), vous allez créer des services qui se verront tous. Et, en bonus, vous pouvez également les dimensionner avec docker-compose (vous pouvez adapter n’importe quel service qui ne lie pas le port à l’hôte)

Voici un exemple de fichier

 version: "2" services: router: build: services/router/ ports: - "8080:8080" auth: build: services/auth/ todo: build: services/todo/ data: build: services/data/ 

Et la référence pour cette nouvelle version du fichier de composition: https://github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md

Pour autant que je sache, en utilisant uniquement Docker, ce n’est pas possible. Vous avez besoin de DNS pour mapper le conteneur ip: s aux noms d’hôtes.

Si vous voulez une solution prête à l’emploi. Une solution consiste à utiliser par exemple Kontena . Il est fourni avec la technologie de superposition réseau de Weave et cette technologie est utilisée pour créer des réseaux LAN privés virtuels pour chaque service et chaque service peut être atteint par service_name.kontena.local-address .

Voici un exemple simple du fichier YAML de l’application WordPress où le service WordPress se connecte au serveur MySQL avec l’adresse wordpress-mysql.kontena.local:

 wordpress: image: wordpress:4.1 stateful: true ports: - 80:80 links: - mysql:wordpress-mysql environment: - WORDPRESS_DB_HOST=wordpress-mysql.kontena.local - WORDPRESS_DB_PASSWORD=secret mysql: image: mariadb:5.5 stateful: true environment: - MYSQL_ROOT_PASSWORD=secret 

Je viens de trouver le blog Tumtum et je suis tombé sur ce paragraphe dans la documentation officielle de Docker . Je ne sais pas si ce paragraphe m’a échappé tout le temps ou si cela a été ajouté récemment, mais cela devrait être exactement ce dont j’ai besoin 🙂