93 votes

Accéder au conteneur Docker depuis l'hôte en utilisant le nom du conteneur

Je développe un service et j'utilise docker compose pour faire tourner des services comme postgres, redis, elasticsearch. J'ai une application web qui est basée sur RubyOnRails et 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 faire un ping sur les conteneurs 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'à présent, tout va bien. Maintenant je veux faire tourner une application ruby on rails sur ma machine hôte mais être capable d'accéder à l'instance postgres avec une url du type postgresql://username:password@postgres/database actuellement, ce n'est 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 vois 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 suis pas sûr de ce que je dois faire ensuite. J'ai essayé de jouer un peu avec /etc/resolv.conf , principalement avec nameserver mais cela n'a pas eu d'effet.

J'apprécierais toute aide ou suggestion sur la manière de configurer correctement cette installation.

MISE À JOUR

Après avoir parcouru les ressources Internet, j'ai réussi à attribuer des adresses IP statiques aux boîtiers. Pour l'instant, cela me suffit pour continuer le développement. Voici ma version actuelle 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

55voto

deFreitas Points 17

Il existe une application opensource qui résout ce problème, elle s'appelle Serveur proxy DNS , Voici quelques exemples du dépôt officiel

Il s'agit d'un serveur DNS qui résout les noms d'hôte des conteneurs. Si un nom d'hôte ne correspond pas, il est également résolu à partir de l'internet.

Démarrer le serveur DNS

$ 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 reviendra à l'original lorsqu'il s'arrêtera).

Création de conteneurs pour les tests

vérification du fichier docker-compose

$ 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

Résoudre les problèmes de contenants

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

à partir d'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

Il résout également le problème des noms d'hôte sur 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

0 votes

C'est exactement ce que je recherchais à l'époque. Lorsque je reprendrai ce projet, je ne manquerai pas d'essayer votre solution !

4 votes

Il convient de noter que cette solution ne fonctionne pas sous OSX. Les resolv.conf n'est malheureusement pas utilisé pour la résolution DNS.

1 votes

Ce n'est pas non plus une option si vous avez un utilisateur de Windows dans votre équipe de développement ;)

11voto

Johan Points 89

Si vous n'utilisez votre installation docker-compose que localement, vous pouvez mapper les ports de vos conteneurs vers votre hôte avec

elasticsearch:
  image: elasticsearch:2.2
  ports:
    - 9300:9300
    - 9200:9200

Utilisez ensuite localhost:9300 (ou 9200 selon le protocole) à partir de votre application web pour accéder à Elasticsearch.

Une solution plus complexe consiste à exécuter vos propres DNS pour résoudre les noms des conteneurs. Je pense que cette solution est beaucoup plus proche de ce que vous demandez. J'ai toujours utilisé skydns lors de l'exécution locale de kubernetes.

Il existe plusieurs options. Jetez un coup d'œil à https://github.com/gliderlabs/registrator y https://github.com/jderusse/docker-dns-gen . Je n'ai pas essayé, mais vous pourriez potentiellement mapper le port dns à votre hôte de la même manière qu'avec les ports élastiques dans l'exemple précédent et ensuite ajouter localhost à votre resolv.conf pour être capable de résoudre les noms de vos conteneurs à partir de votre hôte.

6voto

Nicolai Points 760

Il existe deux solutions (sauf /etc/hosts ) décrite aquí y aquí

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. 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 est modifiée. Une fois que 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 scripts. Tout ce dont vous avez besoin est de permettre à votre système d'interagir avec cette instance de dnsmasq. Je l'ai enregistré dans systemd-resolved :

$ cat /etc/systemd/resolved.conf

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

2voto

Aditya C S Points 138

Le nom d'hôte du conteneur docker n'est pas visible de l'extérieur. Ce que vous pouvez faire est d'assigner un nom au conteneur et d'accéder au conteneur par ce nom. Si vous liez 2 conteneurs, par exemple Container1 et Container2, Docker se charge d'écrire l'IP et le nom d'hôte du Container2 dans le Container1. Cependant, dans votre cas, votre application s'exécute sur la machine hôte.

O

Vous connaissez l'adresse IP du conteneur. Ainsi, dans le fichier /etc/hosts de votre machine hôte, vous pouvez ajouter $IP $hostanameof container

0voto

Christophe Schmitz Points 1821

Aditya a raison. 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 de 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, et vous devrez donc mettre à jour votre fichier /etc/hosts.

Si c'est le cas, je vous recommande de lire cet article de blog qui explique comment obliger un conteneur à obtenir une adresse IP spécifique :

https://xand.es/2016/05/09/docker-with-known-ip/

0 votes

J'ai pensé à cette approche, mais elle est beaucoup trop fastidieuse pour être utilisée à long terme pour le développement.

0 votes

L'adresse IP peut changer à chaque fois que le conteneur est redémarré, cette solution n'est donc pas extensible.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X