Подтвердить что ты не робот

Доступ к контейнеру докера из узла с использованием имен контейнеров

Я разрабатываю услугу и использую там docker compose для вращения сервисов, таких как postgres, redis, elasticsearch. У меня есть веб-приложение, основанное на RubyOnRails, и записывает и читает все эти службы.

Вот мой 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

И я могу пинговать контейнеры в этой сети

$ docker-compose run redis /bin/bash
[email protected]:/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
...

Пока все хорошо. Теперь я хочу запустить ruby ​​on rails application на моем хост-компьютере, но иметь возможность доступа к экземпляру postgres с URL-адресом, например postgresql://username:[email protected]/database, в настоящее время это невозможно

$ ping postgres
ping: unknown host postgres

Я вижу свою сеть в докере

$ docker network ls
NETWORK ID          NAME                DRIVER
ac394b85ce09        bridge              bridge              
0189d7e86b33        elephant_default    bridge              
7e00c70bde3b        elephant_frontapp   bridge              
a648554a72fa        host                host                
4ad9f0f41b36        none                null 

И я вижу интерфейс к нему

$ 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)
...

Но я не уверен, что мне делать дальше. Я попытался немного поиграть с /etc/resolv.conf, главным образом с директивой nameserver, но это не повлияло.

Я был бы признателен за любую помощь в предложениях, как правильно настроить эту настройку.

UPDATE

После просмотра интернет-ресурсов мне удалось назначить статические IP-адреса для ящиков. На данный момент мне достаточно продолжать развитие. Вот мой текущий 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
4b9b3361

Ответ 1

Существует решение с открытым исходным кодом, которое решает эту проблему, оно называется DNS Proxy Server, вот несколько примеров из официального репозитория

Это DNS-сервер, который решает имена хостов контейнеров, если не может найти подходящее имя хоста, а затем решает его из Интернета.

Запустить 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

Он будет автоматически установлен как ваш DNS по умолчанию (и восстановится к исходному, когда он остановится)

Создание нескольких контейнеров для теста

проверка 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

стартовые контейнеры

$ docker-compose up

Решающие контейнеры

от хозяина

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

из другого контейнера

$ 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

Как хорошо это решает интернет-имена хостов

$ 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

Ответ 2

Если вы используете локальную настройку docker-compose, вы можете сопоставить порты из своих контейнеров с вашим хостом с помощью

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

Затем используйте localhost: 9300 (или 9200 в зависимости от протокола) из вашего веб-приложения для доступа к Elasticsearch.

Более сложным решением является запуск собственных DNS, которые разрешают имена контейнеров. Я думаю, что это решение намного ближе к тому, о чем вы просите. Раньше я использовал skydns при запуске кубернетов локально.

Есть несколько вариантов. Посмотрите https://github.com/gliderlabs/registrator и https://github.com/jderusse/docker-dns-gen. Я не пробовал, но вы могли бы потенциально сопоставить порт dns с вашим хостом так же, как и с эластичными портами в предыдущем примере, а затем добавить localhost в свой resolv.conf, чтобы иметь возможность разрешать имена ваших контейнеров из вашего хоста.

Ответ 3

имя хоста контейнера докера не видно снаружи. Вы можете назначить имя контейнеру и получить доступ к контейнеру через имя. Если вы связываете 2 контейнера с контейнером 1 и контейнером2, тогда докер заботится о записи IP и имени хоста container2 в контейнере1. Однако в вашем случае приложение запускается в хост-машине.

ИЛИ

Вы знаете IP-адрес контейнера. Таким образом, в вашей хост-машине/etc/hosts вы можете добавить $IP $hostanameof container

Ответ 4

Существует два решения (кроме /etc/hosts), описанные здесь и здесь

Я написал собственное решение в Python и реализовал его как службу для обеспечения сопоставления с именем хоста контейнера на свой IP-адрес. Вот он: https://github.com/nicolai-budico/dockerhosts

Он запускает dnsmasq с параметром --hostsdir=/var/run/docker-hosts и обновляет файл /var/run/docker-hosts/hosts каждый раз, когда список запущенных контейнеров был изменен. После изменения файла /var/run/docker-hosts/hosts dnsmasq автоматически обновляет свое сопоставление и контейнер становится доступным по имени узла за секунду.

$ 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

Существуют сценарии установки и удаления. Только вам нужно разрешить вашей системе взаимодействовать с этим экземпляром dnsmasq. Я зарегистрировался в systemd-разрешении:

$ cat /etc/systemd/resolved.conf

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

Ответ 5

Адитья прав. В вашем случае простейшим является жесткий код вашего имени хоста/IP-карты в /etc/hosts

Проблема с этим подходом, однако, заключается в том, что вы не контролируете частный IP-адрес, который будет иметь ваша машина postgres. IP-адрес будет изменяться каждый раз при запуске нового контейнера, поэтому вам нужно будет обновить файл /etc/hosts.

Если это проблема, я бы рекомендовал вам прочитать это сообщение в блоге, в котором объясняется, как обеспечить, чтобы контейнер получил определенный IP-адрес:

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