简体   繁体   English

Mac 主机不喜欢 Docker 容器端口转发

[英]Mac host doesn't like Docker container port forwarding

I am experimenting with Docker for the first time, and am trying to get a Spring Boot web app to run inside a Docker container.我第一次尝试使用 Docker,并试图让 Spring Boot Web 应用程序在 Docker 容器内运行。 I am building the app (which packages up into a self-contained jar) and then adding it to the Docker image (which is what I want).我正在构建应用程序(将其打包到一个独立的 jar 中),然后将其添加到 Docker 映像中(这正是我想要的)。

You can find my SSCCE at this Bootup repo on GitHub , whose README has all the instructions to reproduce what I'm seeing.您可以在 GitHub 上的这个Bootup 存储库中找到我的SSCCE ,其 README 包含重现我所看到内容的所有说明。 But basically:但基本上:

  • I build the web app into a jar我将 Web 应用程序构建到一个 jar 中
  • Run docker build -t bootup .运行docker build -t bootup . which succeeds哪个成功
  • Run docker run -it -p 9200:9200 -d --name bootup bootup and then container seems to start up just fine, as is evidence by the docker ps output below运行docker run -it -p 9200:9200 -d --name bootup bootup然后容器似乎启动得很好,下面的docker ps输出就是证据
  • However, when I point a browser to http://localhost:9200 , I get nothing但是,当我将浏览器指向http://localhost:9200 ,我什么也得不到

docker ps output: 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

The web app is configured to run on port 9200 , not the Java default of 8080. You can see this for yourself by running the app outside of docker (so, just locally on you host machine) by running ./gradlew clean build && java -jar build/libs/bootup.jar . Web 应用程序配置为在端口 9200 上运行而不是Java 默认的 8080 端口。您可以通过运行./gradlew clean build && java -jar build/libs/bootup.jar./gradlew clean build && java -jar build/libs/bootup.jar之外运行应用程序(因此,仅在您的主机上本地运行)亲眼看到这一点./gradlew clean build && java -jar build/libs/bootup.jar

To my knowledge, there is no Firewall running on my host that would be blocking ports (I am on Mac 10.11.5 and verified that System Preferences >> Security & Privacy >> Firewall is turned off).据我所知,我的主机上没有运行会阻止端口的防火墙(我在 Mac 10.11.5 上并验证System Preferences >> Security & Privacy >> Firewall已关闭)。

Can anyone spot where I'm going awry?谁能发现我哪里出错了?


Updates:更新:

I ran a curl , netstat and lsof on the host:我在主机上运行了curlnetstatlsof

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)

And then docker exec 'd into the container and ran another netstat :然后docker exec进入容器并运行另一个netstat

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

Update w/ photos:更新照片:

Picture of my browser (Chrome) pointed to http://localhost:9200 :我的浏览器(Chrome)的图片指向http://localhost:9200

在此处输入图片说明

Picture of the source code at http://localhost:9200 : http://localhost:9200的源代码图片:

在此处输入图片说明

Picture of Chrome Developer Tools inspecting the page at http://localhost:9200 : Chrome 开发者工具在http://localhost:9200检查页面的图片:

在此处输入图片说明

Picture of the Network tab in Chrome Developer Tools: Chrome 开发者工具中Network标签的图片:

在此处输入图片说明

What the heck is going on here?!?!?这到底是怎么回事?!?!? According to the source, the browser should be rendering my Well hello there, from Dockerland!根据消息来源,浏览器应该从 Dockerland渲染我的“你好”! message just fine.消息就好了。 According to the actual browser page, it looks like there is a networking error.根据实际浏览器页面,貌似是网络错误。 And according to Chrome Developer Tools, my app is returning all sorts of HTML/CSS/JS content that is not even remotely apart of my app (check out the source code, see for yourself)!!!而据Chrome开发人员工具,我的应用程序返回的各种HTML / CSS / JS内容的甚至不是远程开我的应用程序(检查出的源代码,看看自己)的!

The Dockerfile doesn't expose 9200 to the daemon. Dockerfile 不会向守护程序公开 9200。 Add添加

EXPOSE 9200

to the Dockerfile before ENTRYPOINT在 ENTRYPOINT 之前到ENTRYPOINT

Assuming you are using Docker Toolbox and not the beta ...假设您使用的是 Docker Toolbox 而不是测试版......

There is a 3 step process for exposing a port properly:正确公开端口有 3 个步骤:

  • use EXPOSE 8080 where 8080 is just a port number in the Dockerfile使用EXPOSE 8080 ,其中 8080 只是Dockerfile 中的一个端口号
  • use -p 8080:8080 in your docker run commanddocker run 命令中使用 -p 8080:8080
  • Make sure that you setup port forwarding in Oracle Virtual Box so that the boot2docker machine is able to receive requests from port 8080.确保在 Oracle Virtual Box 中设置端口转发,以便 boot2docker 机器能够接收来自端口 8080 的请求。

This applies to both Windows and OSX where Docker Toolbox is being used.这适用于使用 Docker Toolbox 的 Windows 和 OSX。 Linux doesn't use Oracle VirtualBox to run docker so those hosts do not need to do the third point Linux 不使用 Oracle VirtualBox 来运行 docker,所以那些主机不需要做第三点

I ran your repo as-is on Docker 1.12 on OSX.我在 OSX 上的 Docker 1.12 上按原样运行了你的 repo。

If you look carefully at your container startup:如果您仔细查看容器启动:

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)

Although application.yml and Dockerfile both contain 9200 , the application is starting on 8080虽然application.yml和 Dockerfile 都包含9200 ,但应用程序在8080上启动

Going to add another answer here because I saw something related to the Github Repo that you posted:在这里添加另一个答案,因为我看到了与您发布的 Github Repo 相关的内容:

So the repo is a spring boot repo with an application.yml file.所以这个 repo 是一个带有 application.yml 文件的 spring boot repo。

Your Dockerfile looks like this:您的 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

Which is adding the built jar to the image.这是将构建的 jar 添加到图像中。 If my understanding is correct, the jar does not include application.yml because:如果我的理解是正确的,jar不包含 application.yml,因为:

  • It is not part of the build (gradle would package the src/main only).它不是构建的一部分(gradle 只会打包 src/main)。 It is sitting on the project root folder它位于项目根文件夹中
  • It is not explicitly added to Docker它没有明确添加到 Docker

So therefore one can assume that your app is actually running on 8080 (the default) at the moment?因此,您可以假设您的应用程序目前实际上在 8080(默认)上运行?

A couple of options that one could try:可以尝试的几种选择:

  • Try exposing 8080 instead of 9200 (or expose both) and see if that makes a difference?尝试公开 8080 而不是 9200(或公开两者),看看是否有区别?
  • The entrypoint command can append the port --server.port=9200 entrypoint 命令可以附加端口--server.port=9200
  • The application.yml file should be added to the image (you might need to add an argument to reference it properly) [ ADD application.yml /opt/bootup , after first ADD command]应将 application.yml 文件添加到映像中(您可能需要添加一个参数以正确引用它)[在第一个ADD命令之后ADD application.yml /opt/bootup ]
  • Include the application.yml file in src/main/resources so that spring boot can pick it up automatically.在 src/main/resources 中包含 application.yml 文件,以便 spring boot 可以自动获取它。

References参考文献

Spring Boot reference documentation on the order of loading for external configuration Spring Boot 参考文档关于外部配置的加载顺序

Good News!好消息! (for MacOSx 10.15.7) (对于 MacOSx 10.15.7)

I found the same issue as you, and I was able to solve it by directly opening VirutalBox connection发现和你一样的问题,直接打开VirutalBox连接就解决了

Go here first:先到这里:

VirtualBox 托管 Docker 图像网络控制器设置 changed to bridged then logged into the virtual machine within VirtualBox改成bridged然后登录VirtualBox内的虚拟机

And found the actual machine's adapter labeled:并发现实际机器的适配器标有:

eth0

after I noted the setting it was originally NAT so I changed to bridged and then在我注意到设置后,它最初是 NAT,所以我更改为桥接,然后

在此处输入图片说明

I was able to use its address vs. localhost.我能够使用它的地址与本地主机。

After I used the public address I used:使用公共地址后,我使用了:

curl -i [bridged_ip_address_here]:9200 curl -i [bridged_ip_address_here]:9200

it then worked flawlessly.然后它完美地工作。

However I also noticed some firewalls and accessibility options that needed permission as well.但是,我也注意到一些防火墙和可访问性选项也需要许可。

辅助功能修复

I pray this helps you.我祈祷这对你有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM