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

Как взаимодействовать между контейнерами Докера через "имя хоста"

Я планирую разделить мой монолитный сервер на многие небольшие контейнеры докеров, но пока не нашел хорошего решения для "межконтейнерной связи". Это мой целевой сценарий:

Target scenario

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

Есть ли какое-либо решение для связи через имена хостов (имена контейнеров) между контейнерами, как в традиционной серверной сети?

4b9b3361

Ответ 1

Изменить: после Docker 1.9 рекомендуется использовать команду docker network (см. ниже fooobar.com/questions/137222/...).


Мое решение - настроить dnsmasq на хосте, чтобы автоматически обновлять запись DNS: записи "A" имеют имена контейнеров и автоматически указывают на IP-адреса контейнеров (каждые 10 секунд). автоматическое обновление script вставляется здесь:

#!/bin/bash

# 10 seconds interval time by default
INTERVAL=${INTERVAL:-10}

# dnsmasq config directory
DNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.}

# commands used in this script
DOCKER=${DOCKER:-docker}
SLEEP=${SLEEP:-sleep}
TAIL=${TAIL:-tail}

declare -A service_map

while true
do
    changed=false
    while read line
    do
        name=${line##* }
        ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name)
        if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed
        then
            service_map[$name]=$ip
            # write to file
            echo $name has a new IP Address $ip >&2
            echo "host-record=$name,$ip"  > "${DNSMASQ_CONFIG}/docker-$name"
            changed=true
        fi
    done < <(${DOCKER} ps | ${TAIL} -n +2)

    # a change of IP address occured, restart dnsmasq
    if [ $changed = true ]
    then
        systemctl restart dnsmasq
    fi

    ${SLEEP} $INTERVAL
done

Убедитесь, что ваш сервис dnsmasq доступен на docker0. Затем запустите контейнер с помощью --dns HOST_ADDRESS, чтобы использовать эту службу mini dns.

Ссылка: http://docs.blowb.org/setup-host/dnsmasq.html

Ответ 2

Новая сетевая функция позволяет подключаться к контейнерам посредством их имя, поэтому, если вы создадите новую сеть, любой контейнер, подключенный к эта сеть может достигать других контейнеров по их названию. Пример:

1) Создать новую сеть

$ docker network create <network-name>       

2) Подключите контейнеры к сети

$ docker run --net=<network-name> ...

или

$ docker network connect <network-name> <container-name>

3) Пинг-контейнер по имени

docker exec -ti <container-name-A> ping <container-name-B> 

64 bytes from c1 (172.18.0.4): icmp_seq=1 ttl=64 time=0.137 ms
64 bytes from c1 (172.18.0.4): icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from c1 (172.18.0.4): icmp_seq=3 ttl=64 time=0.074 ms
64 bytes from c1 (172.18.0.4): icmp_seq=4 ttl=64 time=0.074 ms

Смотрите этот раздел документации;

Примечание.. В отличие от старого links, новая сеть не будет создавать переменные среды и не переносить переменные среды с другими контейнерами.

Эта функция в настоящее время не поддерживает псевдонимы

Ответ 3

Это должно быть что --link для, по крайней мере для части имени хоста.
С докеры 1.10 и PR 19242, которые будут:

docker network create --net-alias=[]: Add network-scoped alias for the container

(см. последний раздел ниже)

Вот что Обновление файла /etc/hosts

В дополнение к переменным среды Docker добавляет запись хоста для исходного контейнера в файл /etc/hosts.

Например, запустите сервер LDAP:

docker run -t  --name openldap -d -p 389:389 larrycai/openldap

И определите образ для проверки этого сервера LDAP:

FROM ubuntu
RUN apt-get -y install ldap-utils
RUN touch /root/.bash_aliases
RUN echo "alias lds='ldapsearch -H ldap://internalopenldap -LL -b
ou=Users,dc=openstack,dc=org -D cn=admin,dc=openstack,dc=org -w
password'" > /root/.bash_aliases
ENTRYPOINT bash

Вы можете выставить контейнер openldap как 'internalopenldap' в тестовом изображении с помощью ссылки:

 docker run -it --rm --name ldp --link openldap:internalopenldap ldaptest

Затем, если вы наберете 'lds', этот псевдоним будет работать:

ldapsearch -H ldap://internalopenldap ...

Это вернет людей. Значение internalopenldap правильно достигнуто из изображения ldaptest.


Конечно, докер 1.7 добавит libnetwork, который предоставляет встроенную реализацию Go для подключения контейнеров, См. Сообщение в блоге.
Он представил более полную архитектуру с моделью контейнерной сети (CNM)

https://blog.docker.com/media/2015/04/cnm-model.jpg

Это обновит CLI Docker новыми командами "network" и документирует, как флаг "-net" используется для назначения контейнеров в сети.


docker 1.10 имеет новый раздел Алиас с сетевым интерфейсом, теперь официально задокументировано в network connect:

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

Продолжая описанный выше пример, создайте еще один контейнер в isolated_nw с сетевым псевдонимом.

$ docker run --net=isolated_nw -itd --name=container6 -alias app busybox
8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17

--alias=[]         

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

Вы можете использовать опцию --link для связи другого контейнера с предпочтительным псевдонимом

Вы можете приостановить, перезапустить и остановить контейнеры, подключенные к сети. Приостановленные контейнеры остаются подключенными и могут быть обнаружены при проверке сети. Когда контейнер остановлен, он не появляется в сети, пока вы не перезапустите его.

Если указано, IP-адрес (-я) контейнера повторно применяется при перезапуске остановленного контейнера. Если IP-адрес больше не доступен, контейнер не запускается.

Один из способов гарантировать доступность IP-адреса - это указать --ip-range при создании сети и выбрать статические IP-адреса извне этого диапазона. Это гарантирует, что IP-адрес не будет передан другому контейнеру, пока этот контейнер не находится в сети.

$ docker network create --subnet 172.20.0.0/16 --ip-range 172.20.240.0/20 multi-host-network

$ docker network connect --ip 172.20.128.2 multi-host-network container2
$ docker network connect --link container1:c1 multi-host-network container2

Ответ 4

РЕДАКТИРОВАТЬ: он больше не кровоточит: http://blog.docker.com/2016/02/docker-1-10/

Оригинальный ответ
Я сражался с ним всю ночь. Если вы не боитесь края кровотечения, последняя версия Docker engine и Docker составляют и реализуют libnetwork.

С правильным конфигурационным файлом (который нужно поместить в версию 2) вы создадите службы, которые все будут видеть друг друга. И, бонус, вы также можете масштабировать их с помощью докеры (вы можете масштабировать любую услугу, которую вы хотите, чтобы не связывать порт на хосте)

Вот пример файл

version: "2"
services:
  router:
    build: services/router/
    ports:
      - "8080:8080"
  auth:
    build: services/auth/
  todo:
    build: services/todo/
  data:
    build: services/data/

И ссылка на эту новую версию файла компоновки: https://github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md

Ответ 5

Насколько я знаю, при использовании только Docker это невозможно. Вам нужно указать DNS для сопоставления контейнера ip: s с именами хостов.

Если вы хотите выйти из готового решения. Одним из решений является использование Kontena. Он поставляется с технологией сетевого оверлея от Weave, и эта технология используется для создания виртуальных частных сетей LAN для каждой службы, и каждая услуга может быть достигнута с помощью service_name.kontena.local-address.

Вот простой пример файла YAML приложения Wordpress, где служба Wordpress подключается к серверу MySQL с помощью wordpress-mysql.kontena.local address:

wordpress:                                                                         
  image: wordpress:4.1                                                             
  stateful: true                                                                   
  ports:                                                                           
    - 80:80                                                                      
  links:                                                                           
    - mysql:wordpress-mysql                                                        
  environment:                                                                     
    - WORDPRESS_DB_HOST=wordpress-mysql.kontena.local                              
    - WORDPRESS_DB_PASSWORD=secret                                                 
mysql:                                                                             
  image: mariadb:5.5                                                               
  stateful: true                                                                   
  environment:                                                                     
    - MYSQL_ROOT_PASSWORD=secret