«Как решить эту проблему» - настроить приложения на прослушивание 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.