9

我第一次尝试使用 Docker,并试图让 Spring Boot Web 应用程序在 Docker 容器中运行。我正在构建应用程序(将其打包到一个独立的 jar 中),然后将其添加到 Docker 映像中(这是我想要的)。

你可以在 GitHub 上的这个Bootup repo中找到我的SSCCE,其 README 包含重现我所看到内容的所有说明。但基本上:

  • 我将网络应用程序构建到一个 jar 中
  • 运行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

Web 应用程序配置为在端口 9200 上运行而不是Java 默认的 8080 端口。您可以通过在 docker 外部运行应用程序(因此,仅在主机上本地)运行./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'd进入容器并运行另一个netstat

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

更新照片:

我的浏览器(Chrome)的图片指向http://localhost:9200

在此处输入图像描述

源代码图片位于http://localhost:9200

在此处输入图像描述

Chrome 开发者工具检查页面的图片http://localhost:9200

在此处输入图像描述

NetworkChrome 开发者工具中的选项卡图片:

在此处输入图像描述

这到底是怎么回事?!?!?根据消息来源,浏览器应该正在渲染我的Well hello there,来自 Dockerland!留言就好了。根据实际浏览器页面,好像是网络错误。根据 Chrome 开发者工具,我的应用程序正在返回各种 HTML/CSS/JS 内容,这些内容甚至属于我的应用程序(查看源代码,自己看看)!!!

4

5 回答 5

2

我在 OSX 上的 Docker 1.12 上按原样运行了您的存储库。

如果你仔细查看你的容器启动:

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

于 2016-08-29T20:56:05.993 回答
2

假设您使用的是 Docker Toolbox 而不是 beta ...

正确暴露端口有 3 个步骤:

  • 使用EXPOSE 80808080 只是Dockerfile中的一个端口号
  • 在docker run 命令中使用 -p 8080:8080
  • 确保在 Oracle Virtual Box 中设置端口转发,以便 boot2docker 机器能够接收来自端口 8080 的请求。

这适用于使用 Docker Toolbox 的 Windows 和 OSX。Linux 不使用 Oracle VirtualBox 运行 docker 所以那些主机不需要做第三点

于 2016-08-29T19:58:23.830 回答
2

Dockerfile 不会将 9200 暴露给守护进程。添加

EXPOSE 9200

到 Dockerfile 之前ENTRYPOINT

于 2016-08-29T19:22:57.887 回答
1

将在这里添加另一个答案,因为我看到了与您发布的 Github Repo 相关的内容:

所以这个 repo 是一个带有 application.yml 文件的 spring boot repo。

您的 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

将构建的 jar 添加到图像中。如果我的理解是正确的,jar不包含 application.yml因为:

  • 它不是构建的一部分(gradle 只会打包 src/main)。它位于项目根文件夹中
  • 它没有显式添加到 Docker

因此,可以假设您的应用程序目前实际上是在 8080(默认)上运行的吗?

可以尝试的几个选项:

  • 尝试暴露 8080 而不是 9200(或同时暴露两者),看看是否有区别?
  • entrypoint 命令可以附加端口--server.port=9200
  • 应将 application.yml 文件添加到图像中(您可能需要添加参数以正确引用它) [ ADD application.yml /opt/bootup,在第一个ADD命令之后]
  • 在 src/main/resources 中包含 application.yml 文件,以便 spring boot 可以自动拾取它。

参考

关于外部配置加载顺序的 Spring Boot 参考文档

于 2016-08-29T20:19:44.423 回答
0

好消息!(适用于 MacOSx 10.15.7)

我发现和你一样的问题,直接打开VirutalBox连接就可以解决

先到这里:

VirtualBox 托管 Docker 图像网络控制器设置 更改为桥接然后登录到 VirtualBox 中的虚拟机

并发现实际机器的适配器标有:

eth0

在我注意到它最初是 NAT 的设置之后,所以我改为桥接,然后

在此处输入图像描述

我能够使用它的地址与本地主机。

使用公共地址后,我使用了:

curl -i [bridged_ip_address_here]:9200

然后它完美地工作。

但是,我也注意到一些防火墙和可访问性选项也需要许可。

辅助功能修复

我祈祷这对你有帮助。

于 2020-10-15T17:29:10.270 回答