Вопрос или проблема
У меня есть экземпляр mongo, работающий в контейнере с именем mongo1
, который имеет открытый порт 27017.
Я могу подключиться к нему без проблем с хоста.
У меня есть другой контейнер, в котором работает приложение, которое хочет подключиться к экземпляру mongo.
Как я могу соединить 2 контейнера, чтобы имя хоста mongo1
было доступно для другого контейнера и он мог подключиться к mongo1:27017
?
Проблема заключалась в том, что стандартная сеть docker не позволяет сопоставление name >> DNS
.
Контейнеры в стандартной мостовой сети могут получать доступ друг к другу только по IP-адресам, если вы не используете опцию –link, которая считается устаревшей. В пользовательской мостовой сети контейнеры могут разрешать друг друга по имени или псевдониму.
Поэтому я создал новую сеть:
docker network create -d bridge br0
а затем добавил контейнеры в эту сеть:
docker network connect br0 mongo1
docker network connect br0 wiki
теперь они могут видеть друг друга по имени.
Для существующих контейнеров (как временное решение)
docker inspect <mango_container_name> | grep IPAddress
и отредактировать/добавить /etc/hosts
внутри контейнера
docker exec -it -u 0 <app_container_name> bash
затем изнутри контейнера сопоставить имя_контейнера с IP-адресом.. Пример
echo "172.15.0.5 mango1" >> /etc/hosts
exit
…….
Или вы можете назначить имя хоста для контейнера при его запуске с помощью
docker run -it -h mango1 mango_image
и/или добавьте команду Пример echo "172.17.0.5 mango1" >> /etc/hosts
в файлы docker для меньшей головной боли
Ответ или решение
Для обеспечения взаимодействия между контейнерами Docker по их именам важно понимать, как Docker обрабатывает сеть и какие существуют подходы для достижения требуемой функциональности. Представьте, что у вас есть контейнер с MongoDB с именем mongo1
, который должен быть доступен для другого приложения, работающего в отдельном контейнере. В своей дефолтной конфигурации Docker создаёт мостовую сеть, где контейнеры могут взаимодействовать только через IP-адреса, и чтобы воспользоваться разрешением DNS по именам контейнеров, нам потребуется создать пользовательскую сеть.
Теоретическая часть
Когда вы создаете пользовательскую мостовую сеть, Docker назначает DNS сервером каждую из этих сетей. Это значит, что контейнеры, подключенные к одной пользовательской сети, могут разрешать имена друг друга без необходимости знать их IP-адреса. Это, конечно, удобнее, чем управлять статическим набором IP-адресов, что может быть проблематичным и менее эластичным в сетевом взаимодействии между контейнерами.
Пример решения
Для создания пользовательской сети и подключения к ней контейнеров выполните следующие команды:
docker network create -d bridge br0
docker network connect br0 mongo1
docker network connect br0 wiki
Эти команды создали новую сеть br0
и подключили оба контейнера mongo1
и wiki
к этой сети.
Практическое применение
-
Создание сети: Использование команды
docker network create
создаёт пользовательскую мостовую сеть. Опция-d bridge
указывает Docker на создание мостовой сети. Имя сети, в данном случаеbr0
, должно быть уникальным в пределах вашего Docker-окружения. -
Подключение контейнеров к сети: С помощью команды
docker network connect
вы можете подключать уже запущенные контейнеры к сети. Это даст контейнерам возможность взаимодействовать, используя имена как DNS-алиасы, а не IP-адреса. -
Проверка:
- Убедитесь, что после подключения к одной сети контейнеры могут пинговать друг друга по именам.
- Внутри одного контейнера, например,
wiki
, выполните команду:ping mongo1
Если команды успешно проходят, это указывает на то, что контейнеры могут видеть друг друга с помощью имен.
Альтернативные и временные решения
Для существующих контейнеров можно использовать временное решение – изменить файл /etc/hosts
контейнера:
-
Запросите IP-адрес
mongo1
с помощью команды:docker inspect mongo1 | grep IPAddress
-
Зайдите в контейнер приложения
wiki
:docker exec -it -u 0 wiki bash
-
Добавьте запись в
hosts
с целью маппинга имени контейнера и его IP-адреса:echo "172.17.0.5 mongo1" >> /etc/hosts
-
Выйдите из контейнера, чтобы изменения сохранились:
exit
Передовой опыт
Использование пользовательских сетей для контейнеров Docker является предпочтительным, так как упрощает обслуживание и расширение сетевой конфигурации. Кроме того, автоматическое разрешение имен упрощает управление большими системами, где одним из задач может быть балансировка нагрузки и динамическое масштабирование приложений. Если же у вас есть необходимость в статическом маппинге IP-адресов, это можно автоматизировать через Dockerfile и сценарии конфигурации при запуске контейнеров, минимизируя ручное вмешательство.
Таким образом, следуя приведённым рекомендациям, вы сможете настроить взаимодействие Docker-контейнеров с поддержкой массового разрешения имен, что повысит масштабируемость и управляемость вашего приложения.