🐳 Подключение к службе, запущенной на вашем хосте Docker, из контейнера

Как подключиться из Docker контейнера

by itisgood

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

см. также:

 

 

You may also like

Leave a Comment