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:
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?
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.
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.
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)
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
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
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
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 :)