web-dev-qa-db-de.com

So kommunizieren Sie zwischen Docker-Containern über "Hostname"

Ich habe vor, meinen monolithischen Server in viele kleine Docker-Container aufzuteilen, habe aber noch keine gute Lösung für die "Kommunikation zwischen Containern" gefunden. Dies ist mein Zielszenario:

Target scenario

Ich weiß, wie man Container miteinander verbindet und wie man Ports freigibt, aber keine dieser Lösungen ist für mich zufriedenstellend.

Gibt es eine Lösung für die Kommunikation über Hostnamen (Containernamen) zwischen den Containern wie in einem herkömmlichen Servernetzwerk?

75

Bearbeiten: Nach Docker 1.9 wird der Befehl docker network (Siehe unten https://stackoverflow.com/a/35184695/977939 ) empfohlen, um dies zu erreichen.


Meine Lösung besteht darin, ein DNSMASQ auf dem Host einzurichten, damit der DNS-Eintrag automatisch aktualisiert wird: "A" -Einträge enthalten die Namen von Containern und verweisen automatisch (alle 10 Sekunden) auf die IP-Adressen der Container. Das automatische Aktualisierungsskript wird hier eingefügt:

#!/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

Stellen Sie sicher, dass Ihr dnsmasq-Dienst unter docker0 Verfügbar ist. Starten Sie dann Ihren Container mit --dns Host_ADDRESS, Um diesen Mini-DNS-Dienst zu nutzen.

Referenz: http://docs.blowb.org/setup-Host/dnsmasq.html

25
xuhdev

Mit der neuen Netzwerkfunktion können Sie eine Verbindung zu Containern über deren Namen herstellen. Wenn Sie also ein neues Netzwerk erstellen, kann jeder mit diesem Netzwerk verbundene Container andere Container über deren Namen erreichen. Beispiel:

1) Neues Netzwerk erstellen

$ docker network create <network-name>       

2) Container mit dem Netzwerk verbinden

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

oder

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

3) Ping Container nach Namen

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

Siehe this Abschnitt der Dokumentation;

Hinweis: Im Gegensatz zu Legacy links wird das neue Netzwerk nicht Umgebungsvariablen erstellen oder Umgebungsvariablen mit anderen Containern teilen.

Diese Funktion unterstützt derzeit keine Aliase

177
Hemerson Varela

Das sollte sein wofür --link Ist , zumindest für den Hostnamen-Teil.
Mit docker 1.10 und PR 19242 wäre das:

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

(siehe letzter Abschnitt unten)

Das ist, was Aktualisieren der /etc/hosts - Datei Details

Zusätzlich zu den Umgebungsvariablen fügt Docker der Datei /etc/hosts Einen Host-Eintrag für den Quellcontainer hinzu.

Starten Sie beispielsweise einen LDAP-Server:

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

Und definieren Sie ein Image, um diesen LDAP-Server zu testen:

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

Sie können den Container 'openldap' als 'internalopenldap' im Testbild mit --link anzeigen:

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

Wenn Sie dann 'lds' eingeben, funktioniert dieser Alias:

ldapsearch -H ldap://internalopenldap ...

Das würde Leute zurückbringen. Bedeutung internalopenldap wird korrekt aus dem ldaptest Bild erreicht.


Natürlich wird Docker 1.7 libnetwork hinzufügen, das eine native Go-Implementierung zum Verbinden von Containern bietet . Siehe den Blog Post .
Mit dem Container Network Model (CNM) wurde eine vollständigere Architektur eingeführt.

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

Dadurch wird die Docker-CLI mit neuen "Netzwerk" -Befehlen aktualisiert und dokumentiert, wie das Flag "-net" Zum Zuweisen von Containern zu Netzwerken verwendet wird.


docker 1.10 hat einen neuen Abschnitt Alias ​​mit Netzwerkbereich , jetzt offiziell dokumentiert in network connect :

Während Links die Auflösung privater Namen ermöglichen, die in einem Container lokalisiert sind, bietet der Alias ​​für den Netzwerkbereich eine Möglichkeit, einen Container anhand eines alternativen Namens von einem beliebigen anderen Container im Bereich eines bestimmten Netzwerks zu erkennen.
Im Gegensatz zum Link-Alias, der vom Konsumenten eines Dienstes definiert wird, wird der Netzwerk-Alias ​​durch den Container definiert, der den Dienst dem Netzwerk anbietet.

Fahren Sie mit dem obigen Beispiel fort und erstellen Sie einen weiteren Container in isolated_nw Mit einem Netzwerkalias.

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

--alias=[]         

Fügen Sie einen Netzwerk-Alias ​​für den Container hinzu

Sie können die Option --link Verwenden, um einen anderen Container mit einem bevorzugten Alias ​​zu verknüpfen

Sie können Container, die mit einem Netzwerk verbunden sind, anhalten, neu starten und stoppen. Angehaltene Container bleiben verbunden und können von einer Netzwerkinspektion aufgedeckt werden. Wenn der Container angehalten wird, wird er erst nach einem Neustart im Netzwerk angezeigt.

Wenn angegeben, werden die IP-Adressen des Containers erneut angewendet, wenn ein angehaltener Container neu gestartet wird. Wenn die IP-Adresse nicht mehr verfügbar ist, kann der Container nicht gestartet werden.

Eine Möglichkeit, um sicherzustellen, dass die IP-Adresse verfügbar ist, ist die Angabe eines --ip-range Beim Erstellen des Netzwerks und die Auswahl der statischen IP-Adresse (n) außerhalb dieses Bereichs. Dadurch wird sichergestellt, dass die IP-Adresse keinem anderen Container zugewiesen wird, während sich dieser Container nicht im Netzwerk befindet.

$ 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 [~ # ~] : Es blutet nicht mehr: http://blog.docker.com)/2016/02/docker-1-10 /

Ursprüngliche Antwort
Ich habe die ganze Nacht damit gekämpft. Wenn Sie keine Angst vor "Bleeding Edge" haben, implementieren die neuesten Versionen von Docker-Engine und Docker-Compose beide libnetwork.

Mit der richtigen Konfigurationsdatei (die in Version 2 abgelegt werden muss) erstellen Sie Dienste, die sich gegenseitig sehen. Und, Bonus, Sie können sie auch mit Docker-Compose skalieren (Sie können jeden gewünschten Dienst skalieren, der keinen Port auf dem Host bindet).

Hier ist ein Beispiel Datei

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

Und die Referenz für diese neue Version der Compose-Datei: https://github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md

3
Dolanor

Soweit ich weiß, ist dies nur mit Docker nicht möglich. Sie benötigen DNS, um die IP-Adressen der Container den Hostnamen zuzuordnen.

Wenn Sie eine sofort einsatzbereite Lösung suchen. Eine Lösung besteht darin, zum Beispiel Kontena zu verwenden. Es wird mit der Network-Overlay-Technologie von Weave geliefert. Mit dieser Technologie werden virtuelle private LAN-Netzwerke für jeden Dienst erstellt, und jeder Dienst kann über service_name.kontena.local-address.

Hier ist ein einfaches Beispiel für die YAML-Datei der Wordpress application, wobei Wordpress service mit der Adresse wordpress-mysql.kontena.local eine Verbindung zum MySQL-Server herstellt:

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

Ich habe gerade den Tumtum-Blog gefunden und bin auf diesen Absatz in der offiziellen Docker-Dokumentation gestoßen . Ich weiß nicht, ob ich diesen Absatz die ganze Zeit verpasst habe oder ob er neu hinzugefügt wurde, aber das sollte genau das sein, was ich brauche :)

0