Как подключиться к контейнеру докеров извне хоста (в той же сети) [Windows]

88

Я создал свой первый док-контейнер, на нем запущен сервер, использующий Go, но я не могу получить к нему доступ извне хост-компьютера. Я только начал работать с докером, так что я немного потерялся здесь.

Итак, у меня есть очень простой код Go, запускающий сервер, я создал образ докера, который устанавливает Go и собирает код в базовый образ Linux. Я запускаю сервер на порту 8080, поэтому я предоставляю этот порт хосту, на котором запущен контейнер, следующим образом:

docker run -p 8080:8080 dockertest

Это работает, и я получаю доступ к серверу через IP-адрес машины докера (тот, который появляется в терминале быстрого запуска Docker при запуске), проблема в том, что я не могу получить доступ к веб-сайту, который я размещаю за пределами хоста, поэтому, если я попытаюсь чтобы открыть тот же IP-адрес на моем телефоне, я получаю сообщение об ошибке: эта веб-страница недоступна (ERR_CONNECTION_TIMED_OUT).

Я также пробовал указать IP вот так:

docker run -p 192.168.0.157:8080:8080 dockertest

Но когда я это сделаю, я не могу получить доступ к веб-сайту ни через IP-адрес докера, ни через указанный IP-адрес в командной строке выше. Я также не уверен, какой IP-адрес я должен написать в этой команде. Я использовал IP-адрес своего компьютера, я также пробовал 127.0.0.1 (localhost), но это дало мне тот же результат: не удалось получить доступ к веб-сайту через любой IP вообще.

Я погуглил эту проблему и нашел много вопросов по StackOverflow, но ни один из них не помог мне решить мою проблему, большинство из них были ориентированы на Linux или Mac, поэтому решение не применимо к моей ситуации.

Кроме того, я могу запустить код Go на моем компьютере и получить доступ к веб-сайту с другого устройства в той же сети через IP-адрес моего компьютера. Я не понимаю, почему я не могу получить к нему доступ, когда я запускаю его на докере, мне пришло в голову, что это может иметь какое-то отношение к переадресации IP или чему-то еще, но я полный нуб в сети, я Я в основном веб-разработчик и почти не имею опыта работы с нативным языком.

красная соль
источник
вы использовали EXPOSE 8080 в своем Dockerfile вместе с опцией -p? Также убедитесь, что порт 8080 на поле, где работает ваш контейнер, не заблокирован вашими правилами безопасности.
keda
@keda Да, файл Dockerfile действительно содержит EXPOSE 8080. Я запускаю контейнер локально на своем компьютере через терминал быстрого запуска Docker, я также пытался отключить брандмауэр Windows, но это тоже не сработало, я не знаю, есть ли какие-то настройки. я пропал без вести
redsalt

Ответы:

90

TL; DR Проверьте сетевой режим вашего хоста VirtualBox - он должен быть, bridgedесли вы хотите, чтобы виртуальная машина (и контейнер Docker, на котором она размещена) были доступны в вашей локальной сети.


Похоже, ваша путаница заключается в том, к какому хосту подключиться, чтобы получить доступ к вашему приложению через HTTP. Вы на самом деле не объяснили, какая у вас конфигурация - я собираюсь сделать несколько предположений, основываясь на том факте, что у вас есть «Windows» и «VirtualBox» в ваших тегах.

Я предполагаю, что у вас есть Docker, работающий на какой-то разновидности Linux, работающей в VirtualBox на хосте Windows. Я собираюсь обозначить IP-адреса следующим образом:

D = IP-адрес контейнера Docker

L = IP-адрес хоста Linux, работающего в VirtualBox

W = IP-адрес хоста Windows

Когда вы запускаете приложение Go на хосте Windows, вы можете подключиться к нему http://W:8080/из любой точки локальной сети. Это работает, потому что приложение Go связывает порт 8080 на машине с Windows, и любой, кто пытается получить доступ к порту 8080 по IP-адресу, Wбудет подключен.

И вот здесь все усложняется:

VirtualBox, когда он устанавливает виртуальную машину (ВМ), может настроить сеть в одном из нескольких различных режимов. Я не помню, какие есть разные варианты, но тот, который вам нужен, есть bridged. В этом режиме VirtualBox подключает виртуальную машину к вашей локальной сети, как если бы это была отдельная машина в сети, как и любая другая машина, подключенная к вашей сети. В bridgedрежиме виртуальная машина появляется в вашей сети, как и любая другая машина. В других режимах все настроено иначе, и машина не будет видна в вашей сети.

Итак, если вы правильно настроили сеть для хоста Linux ( bridged), хост Linux будет иметь IP-адрес в вашей локальной сети (что-то вроде 192.168.0.x), и вы сможете получить доступ к своему контейнеру Docker по адресу http://L:8080/.

Если хост Linux установлен в какой-либо режим, отличный от bridged, вы можете получить доступ с хоста Windows, но это будет зависеть от того, в каком именно режиме он находится.

РЕДАКТИРОВАТЬ - судя по комментариям ниже, похоже, что описанная выше ситуация верна.

Давайте сделаем резервную копию: вот как Docker работает на моем компьютере (Ubuntu Linux).

Представьте себе , я запускаю ту же команду , вы должны: docker run -p 8080:8080 dockertest. Это запускает новый контейнер на основе dockertestобраза и перенаправляет (подключает) порт 8080 на хосте Linux (мой компьютер) на порт 8080 на контейнере. Docker настраивает собственную внутреннюю сеть (со своим собственным набором IP-адресов), чтобы демон Docker мог взаимодействовать, а контейнеры - друг с другом. Итак, в основном то, что вы делаете с этим, -p 8080:8080- это соединение внутренней сети Docker с «внешней» сетью, т.е. сетевой адаптер хоста - на конкретный порт.

Со мной так далеко? Хорошо, теперь давайте сделаем шаг назад и посмотрим на вашу систему. На вашем компьютере работает Windows - Docker (в настоящее время) не работает в Windows, поэтому используемый вами инструмент настроил хост Linux на виртуальной машине VirtualBox. Когда вы делаете это docker runв своей среде, происходит то же самое - порт 8080 на хосте Linux соединяется с портом 8080 на контейнере. Большая разница здесь в том, что ваш хост Windows не является хостом Linux, на котором работает контейнер, поэтому здесь есть еще один уровень, и это связь через этот уровень, на котором вы сталкиваетесь с проблемами.

Вам нужно одно из двух:

  1. для подключения порта 8080 на виртуальной машине VirtualBox к порту 8080 на хосте Windows, точно так же, как вы подключаете контейнер Docker к порту хоста.

  2. чтобы подключить виртуальную машину VirtualBox напрямую к вашей локальной сети в bridgedописанном выше сетевом режиме.

Если вы выберете первый вариант, вы сможете получить доступ к контейнеру, http://W:8080где Wнаходится IP-адрес или имя хоста Windows. Если вы выберете второй вариант, вы сможете получить доступ к контейнеру, в http://L:8080котором Lнаходится IP-адрес или имя хоста виртуальной машины Linux.

Итак, это все объяснение более высокого уровня - теперь вам нужно выяснить, как изменить конфигурацию виртуальной машины VirtualBox. И вот здесь я не могу вам помочь - я не знаю, какой инструмент вы используете для всего этого на своем компьютере с Windows, и я совсем не знаком с использованием Docker в Windows.

Если вы можете перейти в окно конфигурации VirtualBox, вы можете внести изменения, описанные ниже. Существует также клиент командной строки, который изменяет виртуальные машины, но я с этим не знаком.

Для bridgedрежима (и это действительно самый простой выбор) выключите виртуальную машину, нажмите кнопку «Настройки» вверху и измените сетевой режим на bridged, затем перезапустите виртуальную машину, и все готово. Виртуальная машина должна получать IP-адрес в вашей локальной сети через DHCP и должна быть видна другим компьютерам в сети по этому IP-адресу.

Kryten
источник
1
Я могу найти только 2 IP-адреса: тот, который Docker показывает, когда я открываю терминал быстрого запуска (192.168.99.100), и тот, который есть на моем компьютере (192.168.0.157), с помощью которого docker run -p 8080:8080 dockertestя могу получить доступ к своему веб-сайту, используя, http://192.168.99.100:8080но только с моего компьютера Windows ( host), а не с моего телефона. Если я использую, docker run -p 192.168.0.157:8080:8080 dockertestя не могу получить доступ к веб-сайту с любого IP-адреса из любого места. Я не уверен, как настроить сеть, я пробовал использовать, --net=bridgeно это тоже не сработало. Могу ли я открыть VirtualBox? Разве я не могу это сделать с помощью терминала Docker?
redsalt
Проблема не в Docker, поэтому нет, Docker вам не поможет. Я собираюсь внести некоторые правки, чтобы проиллюстрировать то, что, как я думаю, происходит.
Kryten
Хорошо спасибо! Теперь я понимаю, что меня сбивает с толку вся часть виртуальной машины Linux. У меня создалось впечатление, что Docker использовал Virtual Box для внутренних вещей, которых я не собирался трогать. На самом деле это было очень просто, мне просто нужно было переключиться на bridgedVirtual Box, и теперь он творит чудеса, большое вам спасибо.
redsalt
Разве нет возможности иметь окна и контейнеры докеров в одной сети, чтобы мы могли напрямую обращаться к контейнерам без перенаправления портов?
Vituel
Наткнулся на это при поиске запущенного сервера Jupyter в докере и попытке получить к нему доступ через локальную сеть. Есть ли способ узнать, что такое L после переключения режима на мост?
PaulDong 06
121
  1. Откройте Oracle VM VirtualBox Manager
  2. Выберите виртуальную машину, используемую Docker
  3. Нажмите Настройки -> Сеть.
  4. Адаптер 1 должен (по умолчанию?) Быть «Подключен к: NAT»
  5. Нажмите Advanced -> Port Forwarding.
  6. Добавьте правило: протокол TCP, порт хоста 8080, гостевой порт 8080 (оставьте IP хоста и гостевой IP пустыми)
  7. Гость - это ваш док-контейнер, а Хост - ваша машина

Теперь вы можете перейти к своему контейнеру через localhost: 8080 и your-internal-ip: 8080.

Дэйви Чу
источник
10
Подтверждено, красиво и легко.
Дирк
2
лучший ответ, нет огромного описания, как у выбранного
Амир Кайюм Хан
2
для бродячих пользователей добавьте это в vagrantfile: config.vm.network «forwarded_port», гость: 8080, хост: 8080, протокол: «tcp»
Винс Верховен
3
Эй! Это сработало как шарм! Благодарность!!!! Я часами пытаюсь понять это.
Джозеф Фриман
2
Это фантастическое решение для всех, кто запускает Docker через VBox!
Mirodinho
7

Попробовав несколько вещей, это сработало для меня:

  • используйте флаг докера --publish = 0.0.0.0: 8080: 8080
  • установите сетевой режим виртуального бокса на NAT и не используйте переадресацию портов

С адресами, отличными от 0.0.0.0меня, успеха не имел.

Мнибер
источник
4

TL; DR: если у вас включен брандмауэр Windows, убедитесь, что есть исключение для «vpnkit» в частных сетях.

В моем конкретном случае я обнаружил, что брандмауэр Windows блокирует мое соединение, когда я пытался посетить опубликованный порт моего контейнера с другого компьютера в моей локальной сети, потому что его отключение заставляло все работать.

Однако я не хотел полностью отключать брандмауэр только для того, чтобы получить доступ к службе моего контейнера. Это вызвало вопрос о том, какое «приложение» слушает от имени службы моего контейнера. Обнаружив еще один поток SO, который научил меня использовать netstat -a -bдля обнаружения приложений, стоящих за сокетами для прослушивания на моем компьютере, я узнал, что это были vpnkit.exe, которые уже имели запись в моих настройках брандмауэра Windows: но «частные сети» были отключены на нем, и как только я его включил, я смог посетить службу моего контейнера с другого компьютера без необходимости полностью отключать брандмауэр.

Атул Варма
источник
Сэр, вы спасли меня от многих часов разочарования. Спасибо.
Бехдад
2

Это наиболее частая проблема, с которой сталкиваются пользователи Windows при запуске контейнеров Docker. ИМО, это «вопрос на миллион долларов по Docker»; @ "Rocco Smit" справедливо указал, что "входящий трафик был отключен по умолчанию на брандмауэре моей хост-машины"; в моем случае - программа McAfee Anti Virus. Я добавил дополнительные порты для входящего трафика с других компьютеров в той же сети Wi-Fi в настройках брандмауэра McAfee; тогда это было волшебство. Более недели я боролся за просмотр по всему Интернету, документацию SO, Docker, учебники за учебниками, связанные с сетью Docker, и множество иллюстраций «не поддерживается в Windows» для «macvlan», «ipvlan», «пользователя» определил мост "и даже пару раз тот же тред SO. Я даже начал просматривать Google со словами «кто-нибудь, кто использует Docker в производственной среде?» (Да, я знаю, что Linux более популярен для рабочих нагрузок Prod по сравнению с серверами Windows), поскольку я не мог получить доступ (со своего мобильного телефона в том же домашнем Wi-Fi) к nginx приложение, развернутое в контейнере Docker в Windows. В конце концов, что в этом хорошего, если вы не можете получить доступ к приложению (развернутому в контейнере Docker) с других компьютеров / устройств, по крайней мере, в той же локальной сети; В конечном итоге в моем случае проблема заключалась только в том, что брандмауэр блокировал входящий трафик; если вы не можете получить доступ к приложению (развернутому в контейнере Docker) с других компьютеров / устройств, по крайней мере, в той же локальной сети; В конечном итоге в моем случае проблема заключалась только в том, что брандмауэр блокировал входящий трафик; если вы не можете получить доступ к приложению (развернутому в контейнере Docker) с других компьютеров / устройств, по крайней мере, в той же локальной сети; В конечном итоге в моем случае проблема заключалась только в том, что брандмауэр блокировал входящий трафик;

банараси
источник
0

Я обнаружил, что наряду с установкой значений порта -p Docker для Windows использует vpnkit, и входящий трафик, поскольку он был отключен по умолчанию на брандмауэре моего хост-компьютера. После включения правил входящего TCP для vpnkit я смог получить доступ к своим контейнерам с других машин в локальной сети.

Рокко Смит
источник