Accéder au conteneur docker depuis l'hôte en utilisant le nom du conteneur
je suis en train de développer un service et d'Y utiliser docker compose pour faire tourner des services comme postgres, redis, elasticsearch. J'ai une application web qui est basée sur RubyOnRails et écrit et lit de tous ces services.
Voici mon docker-compose.yml
version: '2'
services:
redis:
image: redis:2.8
networks:
- frontapp
elasticsearch:
image: elasticsearch:2.2
networks:
- frontapp
postgres:
image: postgres:9.5
environment:
POSTGRES_USER: elephant
POSTGRES_PASSWORD: smarty_pants
POSTGRES_DB: elephant
volumes:
- /var/lib/postgresql/data
networks:
- frontapp
networks:
frontapp:
driver: bridge
Et je peux faire un ping conteneurs à l'intérieur de ce réseau
$ docker-compose run redis /bin/bash
root@777501e06c03:/data# ping postgres
PING postgres (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: icmp_seq=0 ttl=64 time=0.346 ms
64 bytes from 172.20.0.2: icmp_seq=1 ttl=64 time=0.047 ms
...
So far So good. Maintenant je veux lancer l'application ruby on rails sur ma machine hôte mais être capable d'accéder à l'instance de postgres avec des url comme postgresql://username:password@postgres/database
actuellement ce n'est pas possible
$ ping postgres
ping: unknown host postgres
je peux voir mon réseau dans le panneau
$ docker network ls
NETWORK ID NAME DRIVER
ac394b85ce09 bridge bridge
0189d7e86b33 elephant_default bridge
7e00c70bde3b elephant_frontapp bridge
a648554a72fa host host
4ad9f0f41b36 none null
Et je peux voir une interface
$ ifconfig
br-0189d7e86b33 Link encap:Ethernet HWaddr 02:42:76:72:bb:c2
inet addr:172.18.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:76ff:fe72:bbc2/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:36 errors:0 dropped:0 overruns:0 frame:0
TX packets:60 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2000 (2.0 KB) TX bytes:8792 (8.7 KB)
br-7e00c70bde3b Link encap:Ethernet HWaddr 02:42:e7:d1:fe:29
inet addr:172.20.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:e7ff:fed1:fe29/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1584 errors:0 dropped:0 overruns:0 frame:0
TX packets:1597 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:407137 (407.1 KB) TX bytes:292299 (292.2 KB)
...
mais je ne sais pas ce que je dois faire ensuite. J'ai essayé de jouer un peu avec /etc/resolv.conf
principalement nameserver
directive, mais cela n'a eu aucun effet.
j'apprécierais toute aide de suggestions sur la façon de configurer cette configuration correctement.
UPDATE
Après en parcourant des ressources Internet, j'ai réussi à attribuer des adresses IP statiques à des boîtes. Pour l'instant, il me suffit de poursuivre le développement. Voici mon docker-compose.yml
version: '2'
services:
redis:
image: redis:2.8
networks:
frontapp:
ipv4_address: 172.25.0.11
elasticsearch:
image: elasticsearch:2.2
networks:
frontapp:
ipv4_address: 172.25.0.12
postgres:
image: postgres:9.5
environment:
POSTGRES_USER: elephant
POSTGRES_PASSWORD: smarty_pants
POSTGRES_DB: elephant
volumes:
- /var/lib/postgresql/data
networks:
frontapp:
ipv4_address: 172.25.0.10
networks:
frontapp:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.25.0.0/16
gateway: 172.25.0.1
5 réponses
il y a une application opensource qui résout ce problème, elle s'appelle DNS Proxy Server
c'est un serveur DNS qui résout des noms d'hôtes de conteneurs, si ne pouvait pas trouver un nom d'hôte qui correspond alors le résoudre à partir d'internet aussi bien
démarrer le serveur DNS
$ 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 se définira comme votre DNS par défaut automatiquement (et récupérera à l'original quand s'arrête)
démarrer votre container pour test
docker-compose up
menu fixe-composer.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
maintenant, résolvez vos noms d'hôtes containers
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
à partir d'un autre conteneur
$ docker exec -it redis ping elasticsearch.dev.intranet
PING elasticsearch.dev.intranet (172.21.0.2): 56 data bytes
ainsi il résout 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
nom d'hôte du conteneur docker ne peut pas être vu de l'extérieur. Ce que vous pouvez faire est d'assigner un nom au conteneur et d'accéder au conteneur à travers le nom. Si vous liez 2 conteneurs, par exemple container1 et container2, alors docker s'occupe d'écrire L'IP et le nom d'hôte de container2 dans le container1. Cependant, dans votre cas, votre application est en cours d'exécution dans la machine hostmachine.
ou
Vous connaissez l'adresse IP du conteneur. Ainsi, dans le fichier/etc / hosts de votre machine hôte, vous pouvez Ajouter $ IP $ hostanameof container
si vous n'utilisez que votre configuration docker-composer localement, vous pouvez mapper les ports de vos conteneurs vers votre hôte avec
elasticsearch:
image: elasticsearch:2.2
ports:
- 9300:9300
- 9200:9200
puis utilisez localhost: 9300 (ou 9200 selon le protocole) à partir de votre application web pour accéder à Elasticsearch.
une solution plus complexe est d'exécuter votre propre dns qui résout les noms de conteneur. Je pense que cette solution est beaucoup plus proche de ce que vous me demandez. J'ai utilisé des skydns pour exécuter des kubernetes. localement.
Il y a quelques options là-bas. Jetez un oeil à https://github.com/gliderlabs/registrator et https://github.com/jderusse/docker-dns-gen. Je n'ai pas essayer, mais vous pourriez potentiellement carte le port dns à votre hôte de la même façon qu'avec l'élastique ports dans l'exemple précédent, puis ajouter localhost pour votre resolv.conf pour être en mesure de résoudre vos noms de conteneur à partir de votre hôte.
il y a deux solutions (sauf /etc/hosts
) décrit ici et ici
j'ai écrit ma propre solution en Python et je l'ai implémentée en tant que service pour fournir une correspondance entre le nom d'hôte du conteneur et son IP. Elle est ici: https://github.com/nicolai-budico/dockerhosts
il lance dnsmasq avec paramètre --hostsdir=/var/run/docker-hosts
et met à jour le fichier /var/run/docker-hosts/hosts
chaque fois qu'une liste des conteneurs en cours d'exécution a été changée.
Une fois le fichier/var/run/docker-hosts/hosts
est changée, DN-MSQ met automatiquement à jour sa cartographie et le conteneur devient disponible par nom d'hôte dans 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 y a 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 systemd-résolu:
$ cat /etc/systemd/resolved.conf
[Resolve]
DNS=127.0.0.54
#FallbackDNS=
#Domains=
#LLMNR=yes
#MulticastDNS=yes
#DNSSEC=no
#Cache=yes
#DNSStubListener=udp
Aditya a raison. Dans votre cas, le plus simple est de coder votre nom d'hôte / adresse IP en/etc/hosts
Le problème avec cette approche, cependant, est que vous ne contrôlez pas l'adresse IP privée de votre postgres machine. L'adresse IP changera chaque fois que vous démarrez un nouveau conteneur, et vous devrez donc mettre à jour votre fichier /etc/hosts.
Si c'est un problème, je vous recommande de lire cet article de blog qui explique comment appliquer un conteneur obtenir un adresse IP spécifique: