Есть ли способ выставить порт контейнера Docker, связанный с 127.0.0.1 для хоста? - PullRequest
0 голосов
/ 26 сентября 2018

Я запускаю службу внутри контейнера, который привязывается к 127.0.0.1:8888.
Я хочу открыть этот порт для хоста.
Поддерживает ли docker-compose это?

Я пробовал следующеев docker-compose.yml, но не сработало.

expose: 
  - "8888"
ports:
  - "8888:8888"

PS Привязка службы к 0.0.0.0 внутри контейнера в моем случае невозможна.


ОБНОВЛЕНИЕ: Предоставление простогоПример:

docker-compose.yml

version: '3'
services:  
  myservice:
    expose: 
      - "8888"
    ports:
      - "8888:8888"
    build: .

Dockerfile

FROM centos:7
RUN yum install -y nmap-ncat
CMD ["nc", "-l", "-k", "localhost", "8888"]

Команды:

$> docker-compose up --build
$> # Starting test1_myservice_1 ... done
$> # Attaching to test1_myservice_1

$> nc -v -v localhost 8888
$> # Connection to localhost 8888 port [tcp/*] succeeded!
TEST
$>

После ввода TEST вconsole соединение закрыто , что означает , порт на самом деле не выставлен , несмотря на первоначальное сообщение об успехе.Та же проблема возникает с моим реальным сервисом.
Но если я связываю 0.0.0.0 (вместо localhost) внутри контейнера, все работает нормально.

Ответы [ 3 ]

0 голосов
/ 26 сентября 2018

Согласно ответу @BMitch voted «невозможно получить внешний доступ к этому порту напрямую, если контейнер работает с собственным сетевым пространством имен».

Исходя из этого, я думаю, что стоит предложить мой обходной путьПроблема:

Один из способов - установить правило iptables внутри контейнера для перенаправления портов перед запуском службы.Однако для этого требуется, чтобы на хосте явно загружались iptables модули ( в соответствии с этим ).Это в некоторой степени нарушает переносимость.

Мой путь (с использованием socat: пересылка *: от 8889 до 127.0.0.1:8888.)

Dockerfile

...
yum install -y socat
RUN echo -e '#!/bin/bash\n./localservice &\nsocat TCP4-LISTEN:8889,fork 
TCP4:127.0.0.1:8888\n' >> service.sh
RUN chmod u+x service.sh
ENTRYPOINT ["./service.sh"]

docker-compose.yml

version: '3'
services:  
  laax-pdfjs:
    ports:
        # Switch back to 8888 on host
      - "8888:8889"
    build: .
0 голосов
/ 26 сентября 2018

Обычно ответ отрицательный, и почти в каждой ситуации вам следует перенастроить приложение для прослушивания 0.0.0.0.Любая попытка избежать изменения приложения для прослушивания на всех интерфейсах внутри контейнера должна рассматриваться как хак, добавляющий техническую задолженность вашему проекту.


Чтобы развернуть мой комментарий, каждый контейнер по умолчанию запускаетсяв собственном сетевом пространстве имен.Интерфейс обратной связи внутри контейнера отделен от интерфейса обратной связи на хосте и в других контейнерах.Поэтому, если вы слушаете 127.0.0.1 внутри контейнера, все, что находится вне этого пространства имен сети, не сможет получить доступ к порту.Это не то же самое, что прослушивание обратной петли на вашей виртуальной машине и попытка подключиться с другой виртуальной машины к этому порту. Linux не позволяет вам подключиться.

Есть несколько обходных путей:

  1. Выможет взломать iptables для пересылки соединений, но я бы лично этого не делал.Docker в значительной степени основан на автоматических изменениях правил iptables, поэтому ваш риск вступает в конфликт с этой автоматизацией или будет нарушен при следующем воссоздании контейнера.
  2. Вы можете настроить прокси внутри контейнера, который будет прослушивать все интерфейсы и пересылкив петлевой интерфейс.Будет работать что-то вроде nginx.
  3. Вы можете получить вещи в одном и том же сетевом пространстве имен.

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

0 голосов
/ 26 сентября 2018

Проверьте версию составления вашего докера и настройте ее на основе версии.

Файлы составления, которые не объявляют версию, считаются «версией 1».В этих файлах все службы объявлены в корне документа.

Ссылка

Вот как я настраиваю свои порты:

version: "3"

services:
  myservice:
    image: myimage:latest
    ports:
      - "80:80"

Мы можем помочь вам в дальнейшем, если вы сможете поделиться оставшимися вашими docker-compose.yaml.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...