Je développe un service et y utilise docker pour créer des services tels que postgres, redis, elasticsearch. J'ai une application Web basée sur RubyOnRails qui écrit et lit à partir 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 cingler des conteneurs au sein 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
...
Jusqu'ici tout va bien. Maintenant, je veux exécuter Ruby sur Rails sur mon ordinateur hôte, mais pouvoir accéder à l'instance de postgres avec une URL telle que postgresql://username:password@postgres/database
Actuellement. pas possible
$ ping postgres
ping: unknown Host postgres
Je peux voir mon réseau dans docker
$ 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 pour cela
$ 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 suis pas sûr de ce que je devrais faire ensuite. J'ai essayé de jouer un peu avec /etc/resolv.conf
, Principalement avec la directive nameserver
, mais cela n'a eu aucun effet.
J'apprécierais toute aide de suggestions sur la façon de configurer cette configuration correctement.
MISE À JOUR
Après avoir parcouru les ressources Internet, j'ai réussi à attribuer des adresses IP statiques à des boîtes. Pour l'instant, il me suffit de continuer le développement. Voici mon docker-compose.yml
Actuel
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
Il existe une application opensource qui résout ce problème, elle s'appelle Serveur proxy DNS , voici quelques exemples à partir du référentiel officiel
Il s’agit d’un serveur DNS qui résout les noms d’hôte des conteneurs, s’il est impossible de trouver un nom d’hôte correspondant, puis de le résoudre à partir d’Internet également.
$ docker run --hostname dns.mageddo --restart=unless-stopped -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 retrouvera l'original lorsqu'il s'arrête)
vérifier docker-composer le fichier
$ cat docker-compose.yml
version: '3'
services:
nginx-1:
image: nginx
hostname: nginx-1.docker
network_mode: bridge
linux-1:
image: Alpine
hostname: linux-1.docker
command: sh -c 'apk add --update bind-tools && tail -f /dev/null'
network_mode: bridge # that way he can solve others containers names even inside, solve nginx-2, for example
conteneurs de départ
$ docker-compose up
de l'hôte
nslookup nginx-1.docker
Server: 13.0.0.5
Address: 13.0.0.5#53
Non-authoritative answer:
Name: nginx-1.docker
Address: 13.0.0.6
depuis un autre conteneur
$ docker-compose exec linux-1 ping nginx-1.docker
PING nginx-1.docker (13.0.0.6): 56 data bytes
64 bytes from 13.0.0.6: seq=0 ttl=64 time=0.034 ms
De plus, il résout les noms d’hôte Internet
$ nslookup google.com
Server: 13.0.0.5
Address: 13.0.0.5#53
Non-authoritative answer:
Name: google.com
Address: 216.58.202.78
Il y a deux solutions (sauf /etc/hosts
) décrit ici et ici
J'ai écrit ma propre solution dans Python et je l'ai implémentée en tant que service pour fournir un mappage du nom d'hôte du conteneur vers son IP. La 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 a été modifiée. Une fois le fichier /var/run/docker-hosts/hosts
_ change, 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. Vous devez uniquement permettre à votre système d’interagir avec cette instance de Dnsmasq. Je me suis inscrit à systemd-resolu:
$ cat /etc/systemd/resolved.conf
[Resolve]
DNS=127.0.0.54
#FallbackDNS=
#Domains=
#LLMNR=yes
#MulticastDNS=yes
#DNSSEC=no
#Cache=yes
#DNSStubListener=udp
Si vous utilisez uniquement votre configuration de composition de docker localement, vous pouvez mapper les ports de vos conteneurs sur votre hôte avec
elasticsearch:
image: elasticsearch:2.2
ports:
- 9300:9300
- 9200:9200
Ensuite, utilisez localhost: 9300 (ou 9200 selon le protocole) depuis votre application Web pour accéder à Elasticsearch.
Une solution plus complexe consiste à exécuter vos propres DNS qui résolvent les noms de conteneurs. Je pense que cette solution est beaucoup plus proche de ce que vous demandez. J'ai déjà utilisé des skydns lors de l'exécution locale de kubernetes.
Il y a quelques options sur le marché. Jetez un oeil à https://github.com/gliderlabs/registrator et https://github.com/jderusse/docker-dns-gen . Je ne l'ai pas essayé, mais vous pouvez potentiellement mapper le port DNS sur votre hôte de la même manière qu'avec les ports élastiques de l'exemple précédent, puis ajouter localhost à votre resolv.conf pour pouvoir résoudre les noms de vos conteneurs à partir de votre ordinateur. Hôte.
le nom d'hôte du conteneur de menu fixe ne peut pas être vu de l'extérieur. Ce que vous pouvez faire est d’attribuer un nom au conteneur et d’accéder au conteneur par son nom. Si vous liez 2 conteneurs, dites conteneur1 et conteneur2, docker se charge d’écrire l’adresse IP et le nom d’hôte de conteneur2 dans le conteneur1. Cependant, dans votre cas, votre application est exécutée dans la machine hôte.
OR
Vous connaissez l'adresse IP du conteneur. Donc, dans le répertoire/etc/hosts de votre machine hôte, vous pouvez ajouter un conteneur $ IP $ hostanameof
Aditya est correct. Dans votre cas, le plus simple est de coder en dur votre mappage de nom d’hôte/IP dans /etc/hosts
Le problème avec cette approche, cependant, est que vous ne contrôlez pas l’adresse IP privée de votre machine postgres. L'adresse IP changera chaque fois que vous démarrerez un nouveau conteneur. Vous devrez donc mettre à jour votre fichier/etc/hosts.
Si cela pose un problème, je vous recommande de lire ce billet de blog expliquant comment faire en sorte qu'un conteneur obtienne une adresse IP spécifique: