J'ai la version 1.10 de Docker avec le service DNS intégré.
J'ai créé deux conteneurs de service dans mon fichier docker-compose. Ils sont accessibles les uns aux autres par nom d'hôte et par IP, mais quand je voudrais atteindre l'un d'eux depuis la machine hôte, cela ne fonctionne pas, cela ne fonctionne qu'avec IP mais pas avec nom d'hôte.
Alors, est-il possible d'accéder à un conteneur Docker depuis la machine hôte par son nom d'hôte dans le Docker 1.10, s'il vous plaît?
Mise à jour:
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
puis je le démarre par commande: docker-compose up --force-recreate
quand je cours:
docker exec -i -t docker_a ping -c4 docker_b
- Ça marchedocker exec -i -t docker_b ping -c4 docker_a
- Ça marcheping 172.19.0.2
- Ça marche (172.19.0.2
est docker_b
'siroter)ping docker_a
- échoueLe résultat du docker network inspect test_default
est
[
{
"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": {}
}
]
Voici ce que je fais.
J'ai écrit un script Python appelé dnsthing , qui écoute l'API des événements Docker pour le démarrage ou l'arrêt des conteneurs. Il gère un fichier de style hosts
avec les noms et adresses des conteneurs. Les conteneurs sont nommés <container_name>.<network>.docker
, par exemple si je lance ceci:
docker run --rm --name mysql -e MYSQL_ROOT_PASSWORD=secret mysql
J'ai compris:
172.17.0.2 mysql.bridge.docker
J'exécute ensuite un processus dnsmasq
pointant vers ce fichier hosts
. Plus précisément, j'exécute une instance dnsmasq en utilisant la configuration suivante:
listen-address=172.31.255.253
bind-interfaces
addn-hosts=/run/dnsmasq/docker.hosts
local=/docker/
no-hosts
no-resolv
Et j'exécute le script dnsthing
comme ceci:
dnsthing -c "systemctl restart dnsmasq_docker" \
-H /run/dnsmasq/docker.hosts --verbose
Alors:
dnsthing
mises à jour /run/dnsmasq/docker.hosts
lorsque les conteneurs s'arrêtent/démarrentdnsthing
exécute systemctl restart dnsmasq_docker
dnsmasq_docker
exécute dnsmasq
à l'aide de la configuration ci-dessus, lié à une interface de pont local avec l'adresse 172.31.255.253
.Le processus dnsmasq "principal" sur mon système, géré par NetworkManager, utilise cette configuration de /etc/NetworkManager/dnsmasq.d/dockerdns
:
server=/docker/172.31.255.253
Cela indique à dnsmasq de passer toutes les demandes d'hôtes dans le .docker
domaine vers le docker_dnsmasq
un service.
Cela nécessite évidemment un peu de configuration pour tout mettre ensemble, mais après cela, cela semble fonctionner:
$ 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
Comme répondu ici il existe une solution logicielle pour cela, copiant la réponse:
Il existe une application open source qui résout ce problème, elle s'appelle DNS Proxy Server
Il s'agit d'un serveur DNS qui résout les noms d'hôte des conteneurs, et lorsqu'il ne peut pas résoudre un nom d'hôte, il peut le résoudre à l'aide de serveurs de noms publics.
$ 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
Il sera automatiquement défini comme votre DNS par défaut (et reviendra à l'original lorsqu'il s'arrêtera).
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
de l'hôte
$ 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
d'un autre conteneur
$ docker exec -it redis ping elasticsearch.dev.intranet
PING elasticsearch.dev.intranet (172.21.0.2): 56 data bytes
Il résout également les noms d'hôtes Internet
$ 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
La façon la plus simple de le faire est d'ajouter des entrées à votre fichier d'hôtes
127.0.0.1 docker_a docker_b
vers le fichier/etc/hostsdocker-machine ip default
Pour résoudre spécifiquement ce problème, j'ai créé une simple injection de domaine "etc/hosts" outil qui résout les noms des conteneurs Docker locaux sur l'hôte. Exécutez simplement:
docker run -d \
-v /var/run/docker.sock:/tmp/docker.sock \
-v /etc/hosts:/tmp/hosts \
--name docker-hoster \
dvdarias/docker-hoster
Vous pourrez accéder à un conteneur en utilisant le container name
, hostname
, container id
et vía le network aliases
ils ont déclaré pour chaque réseau.
Les conteneurs sont automatiquement enregistrés lorsqu'ils démarrent et retirés lorsqu'ils sont en pause, morts ou arrêtés.
Semblable à @larsks, j'ai écrit un script Python aussi mais je l'ai implémenté en tant que service. Le voici: https://github.com/nicolai-budico/dockerhosts
Il lance dnsmasq avec le paramètre --hostsdir=/var/run/docker-hosts
et met à jour le fichier /var/run/docker-hosts/hosts
chaque fois qu'une liste de conteneurs en cours d'exécution était modifiée. Une fois le fichier /var/run/docker-hosts/hosts
est modifié, dnsmasq met automatiquement à jour son mappage et le conteneur devient disponible par nom d'hôte en une seconde.
$ 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
Il existe des scripts d'installation et de désinstallation. Il vous suffit de permettre à votre système d'interagir avec cette instance dnsmasq. Je me suis inscrit dans résolu par systemd:
$ cat /etc/systemd/resolved.conf
[Resolve]
DNS=127.0.0.54
#FallbackDNS=
#Domains=
#LLMNR=yes
#MulticastDNS=yes
#DNSSEC=no
#Cache=yes
#DNSStubListener=udp