web-dev-qa-db-fra.com

Comment communiquer entre les conteneurs Docker via "hostname"

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

Target scenario

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

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

75
Patrick Gotthard

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


Ma solution consiste à configurer un Dnsmasq sur l'hôte pour que l'enregistrement DNS soit automatiquement mis à jour: les enregistrements "A" ont les noms des conteneurs et pointent automatiquement sur 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

25
xuhdev

La nouvelle fonctionnalité de mise en réseau vous permet de vous connecter aux conteneurs par leur nom. Ainsi, 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 <network-name>       

2) Connectez les conteneurs au réseau

$ docker run --net=<network-name> ...

ou

$ docker network connect <network-name> <container-name>

3) conteneur Ping par nom

docker exec -ti <container-name-A> ping <container-name-B> 

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 la section this de la documentation;

Remarque: Contrairement à l'ancienne version links, le nouveau réseau ne le sera pas créer des variables d'environnement, ni partager des variables d'environnement avec d'autres conteneurs.

Cette fonctionnalité ne prend actuellement pas en charge les alias.

177
Hemerson Varela

Cela devrait être à quoi sert --link , au moins pour la partie nom d’hôte.
Avec menu fixe 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 que Mise à jour du fichier /etc/hosts _ détails

En plus des variables d'environnement, Docker ajoute une entrée d'hôte pour le conteneur source dans le 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 renverrait les gens. La signification de internalopenldap est atteinte à partir de l’image ldaptest.


Bien sûr, docker 1.7 ajoutera libnetwork , qui fournit une implémentation Go native pour la connexion des conteneurs. Voir le blog post .
Il a introduit une architecture plus complète, avec le modèle de réseau de conteneur (CNM)

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

Cela mettra à jour la CLI de Docker avec les nouvelles commandes "network" et documentera la manière dont l'indicateur "-net" est utilisé pour affecter des conteneurs aux réseaux.


le menu fixe 1.10 a une nouvelle section alias de portée 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 portée du réseau fournit un moyen pour qu'un conteneur soit découvert par un nom alternatif par tout autre conteneur dans l'étendue d'un réseau particulier.
Contrairement à l'alias de lien, défini par le consommateur d'un service, l'alias de portée du réseau est défini par le conteneur qui offre le service au réseau.

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

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

--alias=[]         

Ajouter un alias de portée réseau pour le conteneur

Vous pouvez utiliser l’option --link pour associer un autre conteneur à un alias préféré.

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

Si spécifié, la ou les adresses IP du conteneur sont réappliquées lors du redémarrage d'un conteneur arrêté. Si l'adresse IP n'est plus disponible, le conteneur ne parvient pas à démarrer.

Une façon de garantir la disponibilité de l'adresse IP consiste à spécifier un --ip-range lors de la création du réseau et à choisir la ou les adresses IP statiques 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
12
VonC

EDIT: Edge ne saigne plus: http://blog.docker.com/2016/02/docker-1 -10 /

Réponse originale
Je me suis battu avec toute la nuit. Si vous n'avez pas peur de saigner Edge, la dernière version de moteur Docker et composition Docker implémentera libnetwork.

Avec le bon fichier de configuration (à mettre dans la version 2), vous créerez des services qui se verront tous. Et, en prime, vous pouvez également les dimensionner avec docker-compose (vous pouvez redimensionner tout service de votre choix qui ne lie pas le port sur l'hôte).

Voici un exemple 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 compose: https://github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md

3
Dolanor

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

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

Voici un exemple simple de 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
1
Lauri

Je viens de trouver le blog Tumtum et je suis tombé sur ce paragraphe de la documentation officielle de Docker . Je ne sais pas si j'ai raté ce paragraphe tout le temps ou s'il a été ajouté récemment, mais cela devrait être exactement ce dont j'ai besoin :)

0
Patrick Gotthard