Переадресация портов Docker не работает, когда контейнер прослушивает интерфейс localhost - PullRequest
0 голосов
/ 13 октября 2018

У меня проблема с переадресацией портов, которую я не могу решить.Я использую Linux в ВМ и использую докер из этой ВМ.Когда я пытаюсь установить переадресацию портов из docker compose, например:

ports:
   - "3080:3080"

Это работает только в том случае, если приложение, запущенное в контейнере, прослушивает 0.0.0.0:3080.Проблема в том, что большинство приложений, которые я докеризирую, слушают localhost.Любой интерфейс кроме 0.0.0.0 заставляет переадресацию портов не работать.У вас есть идея, почему это происходит или как это решить?

Я работаю:

Версия Docker 17.05.0-ce, сборка 89658be

docker-compose версия 1.17.1, сборка неизвестна

Спасибо

PS Я нашел временный обходной путь.Я указываю сетевой режим «хост» для контейнеров, заставляя контейнер использовать сеть хост-ОС, но этот подход не работает на MacOS.

Ответы [ 2 ]

0 голосов
/ 13 октября 2018

«Как решить эту проблему» - настроить приложения на прослушивание 0.0.0.0.Для коротких сценариев вы часто видите это жестко запрограммированным в основной функции (или даже подразумеваемым библиотекой), но это чрезвычайно распространенный вариант для «настоящих» серверов, и такие вещи вы можете раскрыть с помощью параметра командной строкиили переменная среды.

В терминах «почему»: внутри Docker каждый контейнер работает в изолированном сетевом пространстве имен.Например, если вы попробуете:

$ docker run --rm busybox ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0

Здесь важно то, что у каждого контейнера есть свои localhost, отличающиеся от localhost каждого другого контейнера и localhost* 1010 хоста*.Таким образом, если вы установите контейнер на bind (2) на 127.0.0.1, он будет принимать соединения только от 127.0.0.1 в том же контейнере .

Между тем,Docker запускает для вас уровень трансляции сетевых адресов (NAT).Если вы запустите docker run -p 3080:3080, как вы показываете, а затем (с хоста) запустите iptables -vL, одна из вещей, которую вы найдете, копаясь в этом, - это правило переадресации портов, которое направляет входящие запросы на порт 3080 на хосте, наIP-адрес контейнера (в моем примере 172.17.0.2) через устройство docker0 на порт 3080. В сетевом адресном пространстве контейнера он получит входящее соединение через искусственный контейнерный локальный интерфейс eth0;если бы вы позвонили getsockname (2) в сокет, вы бы увидели адрес 172.17.0.2. Ваш процесс должен принимать соединения через локальный контейнер eth0 интерфейс или все интерфейсы , чтобы быть доступными извне контейнера.

Все это детали реализации;вам почти никогда не придется беспокоиться о чем-либо из этого.Например, поскольку Docker искусственно управляет адресом 172.17.0.0/16, вы не можете получить к ним доступ вне хоста, и они будут меняться между docker run с;для связи между контейнерами (в одной и той же внутренней сети Docker) вы используете их косвенно, но обычно через службу DNS, предоставляемую Docker (так что подключайтесь к other-container-name в качестве имени хоста, которое будет преобразовано в 172.17.0.3),Если вы посмотрите на подробный вывод последовательности запуска некоторых особенно вовлеченных серверов, вы увидите, как они перебирают интерфейсы и связываются со всеми из них явно;но для большинства приложений правильным ответом в пространстве Docker является всегда привязка к 0.0.0.0.

0 голосов
/ 13 октября 2018

Я предлагаю использовать сетевой режим моста в файле docker-compose

driver: bridge
...