web-dev-qa-db-fra.com

Accéder au conteneur de menu fixe à partir de l'hôte à l'aide du nom du conteneur

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
45
Max

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.

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 retrouvera l'original lorsqu'il s'arrête)

Créer des conteneurs pour le test

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

Conteneurs de résolution

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
30
deFreitas

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
5
Nicolai

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.

4
Johan

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

2
Aditya C S

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:

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

1