Хосту Mac не нравится переадресация порта контейнера Docker

Я впервые экспериментирую с Docker и пытаюсь запустить веб-приложение Spring Boot внутри контейнера Docker. Я создаю приложение (которое упаковывается в автономный jar-файл) и затем добавляю его в образ Docker (это то, что я хочу).

Вы можете найти мой SSCCE по этому Репозиторий загрузки на GitHub, в README которого есть все инструкции для воспроизведения того, что я вижу. Но в основном:

  • Я встраиваю веб-приложение в банку
  • Запустите docker build -t bootup ., который преуспевает
  • Запустите docker run -it -p 9200:9200 -d --name bootup bootup, а затем контейнер запустится нормально, о чем свидетельствует вывод docker ps ниже.
  • Однако, когда я указываю браузеру на http://localhost:9200, я ничего не получаю

docker ps вывод:

CONTAINER ID        IMAGE               COMMAND                  CREATED
a8c4ee64a1bc        bootup              "/bin/sh -c 'java -ja"   2 days ago

STATUS              PORTS                    NAMES
Up 12 seconds       0.0.0.0:9200->9200/tcp   bootup

Веб-приложение настроено для работы через порт 9200, не Java по умолчанию 8080. Вы можете убедиться в этом сами, запустив приложение вне докера (то есть только локально на вашем хост-компьютере), запустив ./gradlew clean build && java -jar build/libs/bootup.jar.

Насколько мне известно, на моем хосте не работает брандмауэр, который блокировал бы порты (у меня Mac 10.11.5 и я проверил, что System Preferences >> Security & Privacy >> Firewall отключен).

Может ли кто-нибудь заметить, где я ошибаюсь?


Обновления:

Я запустил curl, netstat и lsof на хосте:

HOST:
curl http://localhost:9200
curl: (52) Empty reply from server

netstat -an | grep 9200
tcp6       0      0  ::1.9200               *.*                    LISTEN     
tcp4       0      0  *.9200                 *.*                    LISTEN 

lsof -n -i4TCP:9200 | grep LISTEN
com.docke 2578 myuser   19u  IPv4 <someHexNumber>      0t0  TCP *:wap-wsp (LISTEN)

А потом docker exec зашел в контейнер и запустил еще netstat:

CONTAINER:
netstat -an | grep 9200
bash: netstat: command not found

Обновление с фотографиями:

Изображение моего браузера (Chrome) указывает на http://localhost:9200:

введите описание изображения здесь

Изображение исходного кода по адресу http://localhost:9200:

введите описание изображения здесь

Изображение инструментов разработчика Chrome, проверяющих страницу по адресу http://localhost:9200:

введите описание изображения здесь

Изображение вкладки Network в инструментах разработчика Chrome:

введите описание изображения здесь

Что, черт возьми, здесь происходит?!?!? Согласно источнику, браузер должен нормально отображать мое сообщение Привет, из Докерленда!. Согласно фактической странице браузера, похоже, что произошла сетевая ошибка. И, согласно инструментам разработчика Chrome, мое приложение возвращает все виды контента HTML/CSS/JS, который даже удалено не отделен от моего приложения (проверьте исходный код, убедитесь сами)!!!


person smeeb    schedule 26.08.2016    source источник
comment
Что произойдет, если вы ударите его завитком? Что произойдет, если вы запустите контейнер — вы уверены, что что-то прослушивает порт?   -  person Oliver Charlesworth    schedule 26.08.2016
comment
Вы уверены, что на 9200 локально уже ничего не работает? У меня было похожее, что докер на Mac не предупреждал, что ему не удалось привязать порт   -  person Paolo    schedule 26.08.2016
comment
Спасибо @OliverCharlesworth (+1) - смотрите мои обновления, есть идеи?   -  person smeeb    schedule 26.08.2016
comment
Спасибо @Paolo (+1) - смотрите мои обновления, есть идеи? Весь код есть на GitHub.   -  person smeeb    schedule 26.08.2016
comment
curl: (52) Пустой ответ от перенаправления портов сервера работает, ваше приложение ничего не выводит.   -  person BMitch    schedule 26.08.2016
comment
Спасибо @BMitch (+1) - так что, если вы клонируете этот репозиторий и запускаете ./gradlew clean build && java -jar build/libs/bootup.jar, вы увидите, что он запускается нормально. Поэтому, когда вы запускаете это локально на своем хосте, оно раскручивается и без проблем обслуживает контент из http://localhost:9200. Это только кажется, когда он запускается изнутри контейнера Docker, где что-то, кажется, душит его или заставляет его действовать шатко. Как выглядит мой Dockerfile? Другими словами, это не проблема моего приложения (как отдельного приложения), это проблема моего приложения, работающего в Docker.   -  person smeeb    schedule 26.08.2016
comment
Я бы посмотрел, но вам нужно запустить что-то за пределами вашего контейнера, прежде чем docker build заработает, и мне неудобно запускать ваш код вне песочницы.   -  person BMitch    schedule 26.08.2016
comment
Многие люди публикуют на StackOverflow SSCCE без Docker, которым доверяет сообщество, но это справедливо! Для других StackOverflowers это просто веб-приложение Spring, которое обслуживает фиктивное HTML-сообщение из базового URL-адреса. Требуется только Java 8.   -  person smeeb    schedule 26.08.2016
comment
@smeeb Попробуйте использовать lsof, чтобы убедиться, что процесс докера действительно прослушивает порт? stackoverflow.com/questions/4421633/   -  person Paolo    schedule 26.08.2016
comment
Спасибо @Paolo (+1) - посмотрите мое обновление. В выводе я изменил только имя пользователя и шестнадцатеричный номер, который, казалось, может быть конфиденциальной информацией для публикации на SO. Но да, похоже, что что-то связанное с докером слушает 9200.   -  person smeeb    schedule 26.08.2016
comment
какую версию докера вы используете? новейшая нативная версия или та, которая основана на виртуальном боксе? скажите, пожалуйста, результат: 1) docker-machine ls 2) docker-machine ip default   -  person Andrea Di Lisio    schedule 28.08.2016
comment
Спасибо @AndreaDiLisio (+1) - я использую Docker для Mac, так что я думаю, что родной. Когда я делаю docker --version, он говорит мне 1.12.0. (1) Вывод docker-machine был очень большим, но начинался с Usage: docker-machine [OPTIONS] COMMAND [arg...]. И (2) вывод docker-machine ip default' is Host не существует: по умолчанию`.   -  person smeeb    schedule 28.08.2016
comment
Можем ли мы увидеть больше dockerfile? Вы открыли 9200 в файле dockerfile?   -  person Mano Marks    schedule 29.08.2016
comment
Два вопроса: 1. Что вы имеете в виду под «ничего не получаю»? 2. Я предполагаю, что curl был от хоста - что вы получаете за тот же curl из контейнера?   -  person creativeChips    schedule 29.08.2016
comment
Спасибо @ManoMarks, полный исходный код находится на GitHub по ссылке, указанной в исходном вопросе, включая Dockerfile.   -  person smeeb    schedule 29.08.2016
comment
Спасибо @creativeChips (+1) - Чтобы ответить на ваши вопросы, (1) извините, чтобы уточнить, я ничего не получаю, означает, что я получаю пустую веб-страницу без содержимого, отправленного с сервера вообще . (2) Если я остановлю свой контейнер Docker и повторно запущу его с помощью показанных выше команд, а затем зайду в контейнер по SSH и запущу curl http://localhost:9200, я получу curl: (7) Failed to connect to localhost port 9200: Connection refused. Мы на что-то, может быть?!? Еще раз спасибо!   -  person smeeb    schedule 29.08.2016
comment
Круто, ты можешь заставить его работать внутри контейнера? ваше приложение работает?   -  person creativeChips    schedule 29.08.2016
comment
Кстати, вы получаете те же результаты для 127.0.0.1?   -  person creativeChips    schedule 29.08.2016
comment
Спасибо @creativeChips (+1 за последние несколько комментариев). Я думаю, ты что-то задумал. Когда я подключился к контейнеру по SSH, я увидел, что bootup.jar на самом деле уже запущен. Пожалуйста, смотрите мои обновления со скриншотами... это что-нибудь значит для вас?!? Итак, похоже, что мое приложение отправляет правильный HTML-код (см. 2-й снимок экрана), но по какой-то причине браузеру это не нравится... и, отвечая на ваш вопрос, нет< /b>, если я укажу браузеру http://127.0.0.1:9200, он буквально получит пустой ответ, и ничего не будет доступно, если я Просмотр исходного кода страницы.   -  person smeeb    schedule 29.08.2016
comment
Что происходит на вкладке Network инструментов разработчика? Особенно код состояния и ответ (внутренняя вкладка Response)   -  person Nitzan Tomer    schedule 29.08.2016
comment
как насчет 0.0.0.0:9200   -  person Marc Young    schedule 29.08.2016
comment
Спасибо @NitzanTomer (+1) - посмотрите мое последнее обновление, я добавил скриншот вкладки Network в Chrome Developer Tools. Кажется, нигде нет вкладки Response, не знаю, что это означает.   -  person smeeb    schedule 29.08.2016
comment
Спасибо @MarcYoung (+1) - когда я перехожу к http://0.0.0.0:9200, я получаю точно такие же результаты, как если бы я перешел к http://127.0.0.1:9200 (см. выше).   -  person smeeb    schedule 29.08.2016
comment
Убедитесь, что вы удалили кэширование. Кроме того, изменилось ли поведение curl? Поделись, пожалуйста. Не мешало бы посмотреть и wget тоже...   -  person creativeChips    schedule 29.08.2016
comment
Спасибо @creativeChips (+1) - curl http://localhost:9200 curl: (52) Empty reply from server и я не ожидаю, что wget будет другим. Также я очистил все кеши и даже зашел в http://localhost:9200 из браузеров, которые раньше даже не открывал. Нет разницы.   -  person smeeb    schedule 29.08.2016
comment
@MarcYoung - когда вы рекомендуете посетить vmip: 9200, какая на самом деле рекомендуемая команда? Допустим, <vmip> — это IP-адрес моего докер-контейнера. Вы предлагаете мне попытаться подключиться к нему по телнету или что-то в этом роде?!?   -  person smeeb    schedule 29.08.2016
comment
Вы проверили, может быть, ваш сервер действительно получает запросы, но, может быть, они ему просто не нравятся и он ведет себя неправильно? Может у тебя логи есть или в консоль печатает?   -  person Nitzan Tomer    schedule 29.08.2016
comment
Спасибо @NitzanTomer, но посмотрите на второй снимок экрана выше. Он возвращает правильный ответ (что HTML должен отображаться как простая веб-страница) в соответствии с источником страницы.   -  person smeeb    schedule 29.08.2016


Ответы (5)


Собираюсь добавить еще один ответ здесь, потому что я видел что-то, связанное с репозиторием Github, которое вы опубликовали:

Таким образом, репо представляет собой репозиторий весенней загрузки с файлом application.yml.

Ваш Dockerfile выглядит так:

FROM openjdk:8

RUN mkdir /opt/bootup

ADD build/libs/bootup.jar /opt/bootup
WORKDIR /opt/bootup
EXPOSE 9200
ENTRYPOINT java -jar bootup.jar

Что добавляет встроенную банку к изображению. Если я правильно понимаю, банка не включает application.yml, потому что:

  • Это не часть сборки (gradle упаковывает только src/main). Он находится в корневой папке проекта
  • Он явно не добавлен в Docker

Таким образом, можно предположить, что ваше приложение на самом деле работает на 8080 (по умолчанию) в данный момент?

Пара вариантов, которые можно попробовать:

  • Попробуйте выставить 8080 вместо 9200 (или выставить оба) и посмотреть, будет ли это иметь значение?
  • Команда entrypoint может добавить порт --server.port=9200
  • Файл application.yml должен быть добавлен к образу (вам может потребоваться добавить аргумент для правильной ссылки на него) [ADD application.yml /opt/bootup, после первой команды ADD]
  • Включите файл application.yml в src/main/resources, чтобы весенняя загрузка могла автоматически подобрать его.

Ссылки

справочная документация по Spring Boot по заказу загрузки для внешней конфигурации

person Shiraaz.M    schedule 29.08.2016
comment
Это интересная теория @Shiraaz (+1). Я попробую это позже сегодня вечером. Думаю, я исходил из предположения, что Gradle встраивает мой application.yml в внутренности последнего убержара. И это вполне может быть, но вы правы, я не уверен на 100% на данный момент. Я попробую и отчитаюсь! Однако тот факт, что исходный код страницы для http://localhost:9200 показывает правильный HTML, заставляет меня сомневаться в этом предложении... следите за обновлениями! - person smeeb; 29.08.2016
comment
При этом скажем (на данный момент), что получается, что Spring ожидает, что файл YAML будет расположен в том же каталоге, что и файл JAR (так что в моем случае /opt/bootup). Можете ли вы сказать мне, какие изменения мне нужно внести в свой Dockerfile, чтобы скопировать/добавить application.yml в /opt/bootup? - person smeeb; 29.08.2016
comment
@smeeb Это очень похоже на то, как вы добавили файл jar. В идеале это должно быть что-то вроде ADD application.yml /opt/bootup после первой команды ADD. Первый аргумент после ADD будет либо application.yml, либо ./application.yml. - person Shiraaz.M; 30.08.2016
comment
Спасибо @Shiraaz (+1) - так что я немного покопался, и похоже, мне нужно сообщить Spring расположение внешнего файла конфигурации. Итак, если я использовал ваш пример и сделал ADD application.yml /op/bootup, мне нужно запустить приложение, используя java -Dspring.config=<LOCATION_OF_YAML> -jar build/libs/bootup.jar. Так будет ли моя команда ENTRYPOINT ENTRYPOINT java -Dspring.config=. -jar bootup.jar или ENTRYPOINT java -Dspring.config=/opt/bootup -jar bootup.jar или чем-то еще? - person smeeb; 30.08.2016
comment
@smeeb Я бы начал с помещения файла в тот же каталог. Он должен автоматически получать файл application.yml без необходимости изменять точку входа. Если он не сработает, вернитесь к добавлению --spring.config.location=file:application.yml в конце точки входа. - person Shiraaz.M; 30.08.2016
comment
Привет, @Shiraaz, пожалуйста, посмотри мой обновленный/отправленный Dockerfile. 2-я команда ADD (то есть ADD application.yml /opt/bootup) не работает. Я могу это сказать, потому что после запуска контейнера и входа в него по SSH (через docker exec -it <containerId> /bin/bash) я вижу только bootup.jar в каталоге /opt/bootup. Любые идеи, где я иду наперекосяк здесь? - person smeeb; 30.08.2016
comment
Кроме того, я ранее пробовал ADD ./application.yml /opt/bootup (добавляя ./ перед именем файла), но это тоже не сработало... мда. - person smeeb; 30.08.2016
comment
@smeeb вы добавили ADD application.yml /op/bootup ... это должно быть «opt», а не «op» :) - person Shiraaz.M; 30.08.2016
comment
Спасибо @Shiraaz - получилось! Большое спасибо, что нашли время, чтобы прочитать все детали и решить эту проблему для меня! - person smeeb; 30.08.2016

Dockerfile не предоставляет демону 9200. Добавлять

EXPOSE 9200

в Dockerfile до ENTRYPOINT

person Mano Marks    schedule 29.08.2016
comment
Спасибо @Mano Marks (+1) - пожалуйста, посмотрите мой загруженный файл Docker... ваше предложение не сработало. Любые идеи? Кроме того, пожалуйста, смотрите мои обновления со снимками экрана... очень странное/неожиданное поведение. - person smeeb; 29.08.2016

Предполагая, что вы используете Docker Toolbox, а не бета-версию...

Существует трехэтапный процесс для правильного раскрытия порта:

  • используйте EXPOSE 8080, где 8080 — это просто номер порта в Dockerfile
  • используйте -p 8080:8080 в вашей команде запуска docker
  • Убедитесь, что вы настроили переадресацию портов в Oracle Virtual Box, чтобы машина boot2docker могла получать запросы с порта 8080.

Это относится как к Windows, так и к OSX, где используется Docker Toolbox. Linux не использует Oracle VirtualBox для запуска докера, поэтому этим хостам не нужно выполнять третий пункт.

person Shiraaz.M    schedule 29.08.2016
comment
Спасибо @Shiraaz (+1), но я использую Docker для Mac который не является Docker Toolbox . Я упоминал об этом несколько раз, в том числе в описании награды. Я не заинтересован в использовании Docker Toolbox, потому что он, как известно, содержит ошибки/шаткости с Mac, поэтому разработчики Docker в первую очередь создали Docker для Mac. - person smeeb; 29.08.2016
comment
Вероятно, это правильный ответ. Он может устранить неполадки, посетив vmip:9200, где vmip — это IP-адрес виртуальной машины. - person Marc Young; 29.08.2016
comment
@MarcYoung Docker для Mac ни для чего не использует VirtualBox. Он использует собственный гипервизор xyhve. - person smeeb; 29.08.2016
comment
@smeeb помните, что docker для mac по-прежнему запускает виртуальную машину под капотом, поскольку он не может по-настоящему размещать докер (виртуальная машина — это то, что загружает ядро ​​Linux). Я оговорился, когда сказал виртуальный бокс. Убедитесь, что сеть работает должным образом для маршрутизации к базовой виртуальной машине. - person Marc Young; 29.08.2016
comment
@smeeb - любопытно, есть ли у вас переадресация портов для работы с докером для Mac? - person Sood; 12.05.2017
comment
Спасибо @ Shiraaz.M. Я использую набор инструментов Docker на Mac (устанавливается через brew). Настройка переадресации портов в Virtual Box помогла. Вы спасли мой день :) - person aietcn; 21.05.2018

Я запустил ваше репо как есть на Docker 1.12 на OSX.

Если вы внимательно посмотрите на запуск вашего контейнера:

2016-08-29 20:52:31.028  INFO 5 --- [           main] o.eclipse.jetty.server.ServerConnector   : Started ServerConnector@47949d1a{HTTP/1.1}{0.0.0.0:8080}
2016-08-29 20:52:31.033  INFO 5 --- [           main] .s.b.c.e.j.JettyEmbeddedServletContainer : Jetty started on port(s) 8080 (http/1.1)

Хотя application.yml и Dockerfile содержат 9200, приложение запускается 8080.

person Marc Young    schedule 29.08.2016
comment
Спасибо @Marc Young - я думаю, Ширааз что-то понял. У меня всегда было впечатление, что Gradle/Spring SDK собирали мой application.yml в окончательный uberjar, и похоже, что это может быть не так (я подтвержу сегодня вечером). Если это так, то Spring вернется к порту по умолчанию 8080, что объясняет то, что вы видите. Таким образом, преобладающая теория здесь (подразумеваемая как Шираазом, так и вами) заключается в том, что Spring не может найти внешний файл конфигурации и по умолчанию использует Java EE по умолчанию 8080. Оставайтесь с нами... (и большое вам спасибо!!! ). - person smeeb; 30.08.2016

Хорошие новости! (для MacOSx 10.15.7)

Я обнаружил ту же проблему, что и вы, и мне удалось решить ее, напрямую открыв соединение VirutalBox.

Иди сначала сюда:

изменен на мостовой, затем выполнен вход на виртуальную машину в VirtualBox.

И нашел адаптер фактической машины с маркировкой:

eth0

после того, как я отметил настройку, изначально это был NAT, поэтому я изменил его на мостовой, а затем

введите здесь описание изображения

Я смог использовать его адрес по сравнению с локальным хостом.

После того, как я использовал публичный адрес, я использовал:

завиток -я [bridged_ip_address_here]:9200

потом работал безотказно.

Однако я также заметил, что некоторые брандмауэры и параметры доступности также требуют разрешения.

Исправление специальных возможностей

Я молюсь, чтобы это помогло вам.

person Don-Pierre Halfaway    schedule 15.10.2020