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



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



Target scenario



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



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

1334   6  

6 ответов:

редактировать: после того, как Докер 1.9, тег docker network команда (см. ниже https://stackoverflow.com/a/35184695/977939) является рекомендуемым способом для достижения этой цели.


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

#!/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 чтобы использовать эту мини-службу dns.

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

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

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

посмотреть этой раздел документации;

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

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

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

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

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

что это обновление /etc/hosts file подробности

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

например, запустите сервер 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

вы можете выставить '' в 'internalopenldap ' в тестовом изображении с --link:

 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 с помощью новых команд "сеть" и задокументирует, как "-net" флаг используется для назначения контейнеров сетям.


настройки 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

редактировать: это больше не кровоточащий край:http://blog.docker.com/2016/02/docker-1-10/

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

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

вот пример file

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

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

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

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

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

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

Я только что нашел Tumtum Blog и наткнулся на этот пункт в официальной документации Докера. Я не знаю, пропустил ли я этот абзац все время или он был недавно добавлен, но это должно быть именно то, что мне нужно:)

Comments

    Ничего не найдено.