Вопрос или проблема
У меня есть экземпляр Mongo, работающий в контейнере с именем mongo1
, который открыл порт 27017. Я могу подключаться к нему без проблем с хоста.
У меня есть другой контейнер, в котором работает приложение, которое хочет подключиться к экземпляру Mongo.
Как я могу соединить два контейнера так, чтобы имя хоста 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, которые предоставляют функционал DNS для разрешения имен контейнеров. Ваша задача заключается в том, чтобы контейнер с приложением мог подключаться к контейнеру MongoDB по имени ‘mongo1’ через порт 27017. Рассмотрим основные этапы этого процесса, обратив внимание на теорию, практические примеры и их применение.
Теория
По умолчанию Docker создает сеть типа bridge, которая позволяет контейнерам взаимодействовать, используя IP-адреса. Однако, это не всегда удобно, так как IP-адреса могут меняться, когда контейнеры пересоздаются. Чтобы обеспечить разрешение имен, Docker рекомендует использовать пользовательские сети bridge, которые поддерживают DNS для контейнеров.
При создании пользовательской сети, Docker автоматически добавляет DNS-записи для всех контейнеров, подключенных к этой сети. Это позволяет контейнерам находиться друг с другом по именам без необходимости вручную изменять файл /etc/hosts
.
Пример
-
Создание пользовательской сети:
Чтобы контейнеры могли видеть друг друга по именам, сначала создайте пользовательскую сеть:
docker network create -d bridge my_custom_network
Параметр
-d bridge
указывает на то, что сеть будет типа bridge, но в отличие от дефолтной сети, будет иметь поддержку DNS. -
Подключение контейнеров к сети:
Подключите оба контейнера к созданной сети:
docker network connect my_custom_network mongo1 docker network connect my_custom_network app_container
Теперь оба контейнера находятся в одной сети и могут использовать DNS для связи.
Применение
После выполнения вышеуказанных шагов, внутри вашего контейнера app_container
вы можете подключиться к MongoDB, используя команду вида:
mongo --host mongo1 --port 27017
Или, если речь идет о какой-то программе на Python, настройте строку подключения к MongoDB с использованием:
from pymongo import MongoClient
client = MongoClient('mongo1', 27017)
Альтернативные методы
-
Конфигурация
/etc/hosts
:Если по каким-то причинам вы не можете использовать пользовательские сети, можно временно использовать следующие команды для добавления записи в файл
/etc/hosts
:Сначала получите IP-адрес контейнера MongoDB:
docker inspect mongo1 | grep IPAddress
Затем, добавьте этот IP-адрес в файл
/etc/hosts
в приложении:docker exec -it -u 0 app_container bash echo "172.17.0.X mongo1" >> /etc/hosts exit
-
Настройка хоста контейнера при запуске:
Добавьте имя хоста при запуске контейнера, используя параметр
-h
:docker run -d -h mongo1 --name mongo1 mongo_image
Таким образом, у вас будет меньше проблем, если нужно будет переразвернуть контейнеры, так как хостовое имя уже будет задано.
Заключение
Использование именованных сетей Docker является современным и удобным способом обеспечения факта того, что ваши контейнеры могут обратиться друг к другу по имени, значительно упрощая их конфигурацию и управление. Это не только делает вашу инфраструктуру более надежной, но также облегчает процессы разработки и тестирования за счет повышения уровня абстракции и совместимости контейнерных приложений.