Обычно ответ отрицательный, и почти в каждой ситуации вам следует перенастроить приложение для прослушивания 0.0.0.0.Любая попытка избежать изменения приложения для прослушивания на всех интерфейсах внутри контейнера должна рассматриваться как хак, добавляющий техническую задолженность вашему проекту.
Чтобы развернуть мой комментарий, каждый контейнер по умолчанию запускаетсяв собственном сетевом пространстве имен.Интерфейс обратной связи внутри контейнера отделен от интерфейса обратной связи на хосте и в других контейнерах.Поэтому, если вы слушаете 127.0.0.1 внутри контейнера, все, что находится вне этого пространства имен сети, не сможет получить доступ к порту.Это не то же самое, что прослушивание обратной петли на вашей виртуальной машине и попытка подключиться с другой виртуальной машины к этому порту. Linux не позволяет вам подключиться.
Есть несколько обходных путей:
- Выможет взломать iptables для пересылки соединений, но я бы лично этого не делал.Docker в значительной степени основан на автоматических изменениях правил iptables, поэтому ваш риск вступает в конфликт с этой автоматизацией или будет нарушен при следующем воссоздании контейнера.
- Вы можете настроить прокси внутри контейнера, который будет прослушивать все интерфейсы и пересылкив петлевой интерфейс.Будет работать что-то вроде nginx.
- Вы можете получить вещи в одном и том же сетевом пространстве имен.
Этот последний способ может быть реализован двумя способами.Между контейнерами вы можете запустить контейнер в пространстве имен сети другого контейнера.Это часто делается для отладки сети, а также для работы стручков в kubernetes.Вот пример запуска второго контейнера:
$ docker run -it --rm --net container:$(docker ps -lq) nicolaka/netshoot /bin/sh
/ # ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 10 127.0.0.1:8888 *:*
LISTEN 0 128 127.0.0.11:41469 *:*
/ # nc -v -v localhost 8888
Connection to localhost 8888 port [tcp/8888] succeeded!
TEST
/ #
Обратите внимание на --net container:...
(я использовал docker ps -lq
, чтобы получить последний запущенный идентификатор контейнера в моей лаборатории).Это позволяет двум отдельным контейнерам работать в одном и том же пространстве имен.
Если вам нужно было получить к нему доступ из-за пределов докера, вы можете удалить пространство имен сети и подключить контейнер непосредственно к сети хоста.Для одноразового контейнера это можно сделать с помощью
docker run --net host ...
В compose это будет выглядеть следующим образом:
version: '3'
services:
myservice:
network_mode: "host"
build: .
Вы можете увидеть документацию по докеру compose для этоговариант здесь .Это не поддерживается в режиме роя, и вы не публикуете порты в этом режиме, так как вы пытаетесь опубликовать порт между одними и теми же сетевыми пространствами имен.
Примечание, expose
не требуется ни для одного изэтот.Он предназначен только для документации и некоторых автоматизированных инструментов, но в остальном не влияет на сетевое соединение между контейнерами и не влияет на возможность публикации определенного порта.