Это может пригодиться, если вы хотите подключиться к базе данных или чему-то еще, не запущенному в Docker.
Мы уже писали об этом, но с тех пор кое-что изменилось, чтобы упростить этот процесс независимо от того, как вы используете Docker.
Вот 2 случая, когда вы можете захотеть это сделать:
Возможно, вы переходите к использованию Docker и еще не готовы перенести свою базу данных в Docker, поэтому хотите подключиться к локально работающей версии PostgreSQL, MySQL или любой другой СУБД, которая у вас есть.
Или, возможно, у вас есть несколько сервисов, которые вы собираетесь перевести в Docker.
Два из них находятся в Docker, но третий сервис еще не запущен в Docker, но двум другим сервисам необходимо подключиться к этому третьему сервису.
Современные версии Docker
Все приведенные ниже варианты позволяют использовать мостовую сеть Docker, не прибегая к использованию параметра –net=host.
Мы воспользуемся преимуществами использования host.docker.internal, которое представляет собой специальное DNS-имя, доступное в вашем контейнере и разрешающееся в IP-адрес шлюза локальной мостовой сети вашего хоста Docker.
Мы расскажем об этом более подробно, когда увидим это в действии, выполнив несколько команд.
Например, если вы хотите подключиться к Postgres, работающему на порту 5432, вы можете настроить свое приложение в Docker на подключение к локальной службе Postgres по адресу host.docker.internal:5432.
Docker Desktop
Если вы используете Docker Desktop, это имя хоста работает из коробки.
Вышеупомянутая функция не нова.
По некоторым данным, она доступна с версии Docker Engine 18.03, которая была выпущена в марте 2018 года.
Скорее всего, она у вас уже есть!
Родной Linux в продакшене
Если вы не используете Docker Desktop, например, в качестве нативного Linux в производстве, у вас есть возможность, которая будет доступна в Docker Engine 20.10+ (вышел в декабре 2020 года).
Она зависит от использования host-gateway – специального значения, которое вы можете использовать с командой –add-host для получения IP-адреса шлюза вашей сети Docker bridge.
Основная идея заключается в том, что вы можете использовать это значение в сочетании с добавлением имени хоста host.docker.internal, чтобы все работало так же, как и в Docker Desktop.
Не используете Docker Compose?
Если вы запускаете свой контейнер напрямую с помощью docker CLI, вы можете добавить этот флаг –add-host=”host.docker.internal:host-gateway” в команду контейнера вашего приложения.
Использовать Docker Compose?
В сервисе вашего приложения вы можете установить это свойство extra_hosts: [“host.docker.internal:host-gateway”], которое делает то же самое, что и выше.
Пробуем с помощью Ping
Выше описано, как все это работает, но некоторые детали немного абстрактны, особенно в отношении таких терминов, как bridge сети и IP-адреса шлюзов.
Попробуйте запустить этот контейнер:
docker container run --rm \
--add-host="host.docker.internal:host-gateway" \
debian:stable-slim \
bash -c "apt-get update && apt-get install -y iputils-ping && ping -c 3 host.docker.internal"
Независимо от того, как вы запускаете Docker (Docker Desktop или родной), вы должны увидеть это:
PING host.docker.internal (172.17.0.1) 56(84) bytes of data.
64 bytes from host.docker.internal (172.17.0.1): icmp_seq=1 ttl=64 time=0.039 ms
64 bytes from host.docker.internal (172.17.0.1): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from host.docker.internal (172.17.0.1): icmp_seq=3 ttl=64 time=0.038 ms
--- host.docker.internal ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2105ms
rtt min/avg/max/mdev = 0.038/0.043/0.054/0.007 ms
Но если вы не используете Docker Desktop и попытаетесь запустить вышеописанную процедуру без флага –add-host, то получите следующую ошибку ping:ping: host.docker.internal: Name or service not known
.
Это потому, что –add-host добавит эту запись в файл /etc/hosts вашего контейнера, например 172.17.0.1 host.docker.internal.
Без этого флага host.docker.internal не может быть найден, и он терпит неудачу.
Кстати, IP-адрес 172.17.0.1 связан с результатом выполнения ip a или ifconfig для сетевого интерфейса docker0, ваш IP-адрес может быть другим.
Это IP-адрес шлюза сети моста, и именно к нему привязан host.docker.internal.
Вы можете напрямую пинговать или обращаться к этому IP-адресу, даже не используя –add-host, но использование DNS поможет избежать необходимости запоминать этот IP-адрес, а в некоторых системах он может быть и не таким, в зависимости от того, как настроена ваша сеть.
Вы можете погрузиться на один уровень глубже и запустить docker network inspect bridge, чтобы увидеть результат.
Примерно на трети пути вниз вы увидите “Gateway”: “172.17.0.1”.
Сказав это, мы переходим к тому, как раньше можно было подключиться к хосту Docker до появления этих современных функций в Docker.
Древние версии Docker
Если вы заблокированы на очень старой версии Docker, у вас есть несколько вариантов.
Если вы заблокированы на очень старой версии Docker, у вас есть несколько вариантов.
Вы можете запустить docker network inspect bridge -f “{{range .IPAM.Config}}{{.Gateway}}{{end}}”, чтобы получить IP-адрес шлюза самостоятельно.
Мы используем систему шаблонов Go для разбора IP-адреса.
Вместо использования host.docker.internal вы можете получить доступ к этому IP напрямую.
На моей машине он возвращает 172.17.0.1, но не гарантировано, что он будет таким на вашей системе, это зависит от того, как настроена ваша сеть.
Я бы использовал описанное выше решение, так как оно не требует внешних зависимостей и не требует пользовательского разбора вывода для получения IP-адреса, но в качестве альтернативы вы можете запустить ip a или сопоставимую команду вашей операционной системы (ifconfig и т. д.), чтобы найти сетевой интерфейс docker0.
На моей машине ip a выдает такой результат:
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:f0:24:c9:09 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:f0ff:fe24:c909/64 scope link
valid_lft forever preferred_lft forever
В строке 3 вы можете увидеть тот же самый IP-адрес 172.17.0.1.
см. также:
- 🐳 Переключение пользователя в образе или контейнере Docker
- 🐳 Как приостановить и возобновить контейнеры Docker
- 🐳 Объяснение концепции сетей в Docker
- 🐳 Docker сетевое взаимодействие 101
- Как создать, перечислить и удалить контейнеры Docker в Linux
- Начало работы с Docker