Как взаимодействовать между контейнерами Докера через "имя хоста"
Я планирую разделить мой монолитный сервер на многие небольшие контейнеры докеров, но пока не нашел хорошего решения для "межконтейнерной связи". Это мой целевой сценарий:
![Target scenario]()
Я знаю, как связывать контейнеры вместе и как выставлять порты, но ни одно из этих решений не удовлетворяет мне.
Есть ли какое-либо решение для связи через имена хостов (имена контейнеров) между контейнерами, как в традиционной серверной сети?
Ответы
Ответ 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
Ответ 6
Я только что нашел Блог Tumtum и наткнулся на этот абзац в официальная документация Docker. Я не знаю, пропустил ли я этот абзац все время или был ли он недавно добавлен, но это должно быть именно то, что мне нужно:)