wake-up-neo.com

Docker 1.10 greift von einem Host-Computer auf einen Container über seinen Hostnamen zu

Ich habe die Docker-Version 1.10 mit eingebettetem DNS-Dienst.

Ich habe zwei Dienstcontainer in meiner Docker-Compose-Datei erstellt. Sie sind untereinander über den Hostnamen und die IP-Adresse erreichbar, aber wenn ich einen von ihnen vom Hostcomputer aus erreichen möchte, funktioniert dies nicht, sondern nur mit der IP-Adresse und nicht mit dem Hostnamen.

Ist es also möglich, über den Hostnamen in Docker 1.10 auf einen Docker-Container vom Host-Computer aus zuzugreifen?

pdate:

docker-compose.yml

version: '2'
services:
    service_a:
        image: nginx
        container_name: docker_a
        ports:
           - 8080:80
    service_b:
        image: nginx
        container_name: docker_b
        ports:
            - 8081:80

dann starte ich es per befehl: docker-compose up --force-recreate

wenn ich renne:

  • docker exec -i -t docker_a ping -c4 docker_b - Es klappt
  • docker exec -i -t docker_b ping -c4 docker_a - Es klappt
  • ping 172.19.0.2 - Es klappt (172.19.0.2 ist docker_b 's ip)
  • ping docker_a - fehlgeschlagen

Das Ergebnis der docker network inspect test_default ist

[
    {
        "Name": "test_default",
        "Id":   "f6436ef4a2cd4c09ffdee82b0d0b47f96dd5aee3e1bde068376dd26f81e79712",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1/16"
                }
            ]
        },
        "Containers": {
             "a9f13f023761123115fcb2b454d3fd21666b8e1e0637f134026c44a7a84f1b0b": {
                "Name": "docker_a",
                "EndpointID":     "a5c8e08feda96d0de8f7c6203f2707dd3f9f6c3a64666126055b16a3908fafed",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            },
                "c6532af99f691659b452c1cbf1693731a75cdfab9ea50428d9c99dd09c3e9a40": {
                "Name": "docker_b",
                "EndpointID":     "28a1877a0fdbaeb8d33a290e5a5768edc737d069d23ef9bbcc1d64cfe5fbe312",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {}
    }
]
31
Adam Bernau

Hier ist was ich tue.

Ich habe ein Python Skript namens dnsthing geschrieben, das die Docker-Ereignis-API auf das Starten oder Stoppen von Containern überwacht und eine Datei im hosts-Stil mit verwaltet Namen und Adressen von Containern Die Container haben den Namen <container_name>.<network>.docker.

docker run --rm --name mysql -e MYSQL_ROOT_PASSWORD=secret  mysql

Ich bekomme das:

172.17.0.2 mysql.bridge.docker

Ich führe dann einen dnsmasq -Prozess aus, der auf diese hosts -Datei zeigt. Insbesondere führe ich eine dnsmasq-Instanz mit der folgenden Konfiguration aus:

listen-address=172.31.255.253
bind-interfaces
addn-hosts=/run/dnsmasq/docker.hosts
local=/docker/
no-hosts
no-resolv

Und ich führe das Skript dnsthing folgendermaßen aus:

dnsthing -c "systemctl restart dnsmasq_docker" \
  -H /run/dnsmasq/docker.hosts --verbose

So:

  • dnsthing aktualisiert /run/dnsmasq/docker.hosts, wenn Container anhalten/starten
  • Nach einem Update führt dnsthingsystemctl restart dnsmasq_docker Aus.
  • dnsmasq_docker Führt dnsmasq mit der obigen Konfiguration aus, die an eine lokale Bridge-Schnittstelle mit der Adresse 172.31.255.253 Gebunden ist.
  • Der "Haupt" -Dnsmasq-Prozess auf meinem System, der von NetworkManager verwaltet wird, verwendet diese Konfiguration von /etc/NetworkManager/dnsmasq.d/dockerdns:

    server=/docker/172.31.255.253
    

    Dies weist dnsmasq an, alle Anforderungen für Hosts in der Domäne .docker An den Dienst docker_dnsmasq Zu übergeben.

Dies erfordert natürlich ein wenig Setup, um alles zusammenzusetzen, aber danach scheint es einfach zu funktionieren:

$ ping -c1  mysql.bridge.docker
PING mysql.bridge.docker (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.087 ms

--- mysql.bridge.docker ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.087/0.087/0.087/0.000 ms
12
larsks

Als hier beantwortet gibt es dafür eine Softwarelösung, die die Antwort kopiert:


Es gibt eine Open Source-Anwendung, die dieses Problem behebt. Sie heißt DNS Proxy Server

Es handelt sich um einen DNS-Server, der Container-Hostnamen auflöst. Wenn ein Hostname nicht aufgelöst werden kann, kann er mit öffentlichen Nameservern aufgelöst werden.

Starten Sie den DNS-Server

$ docker run --hostname dns.mageddo --name dns-proxy-server -p 5380:5380 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /etc/resolv.conf:/etc/resolv.conf \
defreitas/dns-proxy-server

Es wird automatisch als Standard-DNS festgelegt (und es wird auf das Original zurückgesetzt, wenn es gestoppt wird).

Starten Sie Ihren Container für den Test

docker-compose up

docker-compose.yml

version: '2'
services:
  redis:
    container_name: redis
    image: redis:2.8
    hostname: redis.dev.intranet
    network_mode: bridge # that way he can solve others containers names even inside, solve elasticsearch, for example
  elasticsearch:
    container_name: elasticsearch
    image: elasticsearch:2.2
    hostname: elasticsearch.dev.intranet

Lösen Sie nun die Hostnamen Ihrer Container auf

vom Host

$ nslookup redis.dev.intranet
Server:     172.17.0.2
Address:    172.17.0.2#53

Non-authoritative answer:
Name:   redis.dev.intranet
Address: 172.21.0.3

aus einem anderen Container

$ docker exec -it redis ping elasticsearch.dev.intranet
PING elasticsearch.dev.intranet (172.21.0.2): 56 data bytes

Auch Internet-Hostnamen werden aufgelöst

$ nslookup google.com
Server:     172.17.0.2
Address:    172.17.0.2#53

Non-authoritative answer:
Name:   google.com
Address: 216.58.202.78
9
deFreitas

Der einfachste Weg, dies zu tun, ist das Hinzufügen von Einträgen zu Ihrer hosts-Datei

  • für Linux: Fügen Sie 127.0.0.1 docker_a docker_b zur Datei/etc/hosts hinzu
  • für Mac: Ähnlich wie Linux, aber IP der virtuellen Maschine verwenden docker-machine ip default
3
jazgot

Um dieses Problem gezielt zu lösen, habe ich eine einfache Domain-Injection "etc/hosts" erstellt Tool , die die Namen der lokalen Docker-Container auf dem Host auflöst. Lauf einfach:

docker run -d \
    -v /var/run/docker.sock:/tmp/docker.sock \
    -v /etc/hosts:/tmp/hosts \
    --name docker-hoster \
    dvdarias/docker-hoster

Sie können mit container name, hostname, container id Und über das network aliases, Das sie für jedes Netzwerk deklariert haben, auf einen Container zugreifen.

Container werden beim Starten automatisch registriert und entfernt, wenn sie angehalten, tot oder angehalten werden.

2
David Darias

Ähnlich wie bei @larsks habe ich auch ein Python) -Skript geschrieben, es jedoch als Dienst implementiert. Hier ist es: https://github.com/nicolai-budico/dockerhosts

Es startet dnsmasq mit dem Parameter --hostsdir=/var/run/docker-hosts und aktualisiert die Datei /var/run/docker-hosts/hosts jedes Mal, wenn eine Liste laufender Container geändert wurde. Einmal Datei /var/run/docker-hosts/hosts geändert wird, aktualisiert dnsmasq automatisch seine Zuordnung und der Container wird in einer Sekunde nach Hostname verfügbar.

$ docker run -d --hostname=myapp.local.com --rm -it ubuntu:17.10
9af0b6a89feee747151007214b4e24b8ec7c9b2858badff6d584110bed45b740

$ nslookup myapp.local.com
Server:         127.0.0.53
Address:        127.0.0.53#53

Non-authoritative answer:
Name:   myapp.local.com
Address: 172.17.0.2

Es gibt Installations- und Deinstallationsskripte. Sie müssen lediglich zulassen, dass Ihr System mit dieser dnsmasq-Instanz interagiert. Ich habe mich in systemd-resolved registriert:

$ cat /etc/systemd/resolved.conf

[Resolve]
DNS=127.0.0.54
#FallbackDNS=
#Domains=
#LLMNR=yes
#MulticastDNS=yes
#DNSSEC=no
#Cache=yes
#DNSStubListener=udp
1
Nicolai