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:
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?
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.
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
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.
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üpfenSie 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
[~ # ~] 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
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
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 :)