如何从主机外部(同一网络)连接到Docker容器[Windows]


87

我已经创建了我的第一个Docker容器,它使用Go运行服务器,但是无法从主机外部访问它。我刚刚开始使用docker,所以我在这里有点迷路了。

因此,我有一个非常简单的Go代码来启动服务器,我已经构建了Docker映像,该映像安装了Go并在Linux基本映像中构建了代码。我在端口8080上运行服务器,因此我将该端口公开给运行容器的主机,如下所示:

docker run -p 8080:8080 dockertest

那行得通,我可以通过Docker的机器IP启动时出现在Docker Quickstart Terminal的机器IP)访问服务器,问题是我无法从主机外部访问我托管的网站,所以如果我尝试在手机上打开相同的IP地址,只会给我一个错误:该网页不可用(ERR_CONNECTION_TIMED_OUT)。

我也尝试过这样指定IP:

docker run -p 192.168.0.157:8080:8080 dockertest

但是当我这样做时,我既不能通过docker机器的IP也不能通过上面的命令行中的指定IP来访问网站。我也不确定我应该使用该计算机的IP在该命令中写入哪个IP,我也尝试了127.0.0.1(localhost),但结果却是相同的:无法通过任何方式访问该网站知识产权。

我已经搜索了这个问题,发现了许多StackOverflow问题,但都没有帮助我解决问题,大多数问题都针对Linux或Mac,因此该解决方案不适用于我的情况。

另外,我可以在计算机上运行Go代码,并通过计算机的IP从同一网络中的另一台设备访问网站。我不明白为什么在docker机器上运行它时无法访问它,我想到它可能与IP转发有关,但我是网络领域的一个完全菜鸟。我主要是一名Web开发人员,几乎没有本地经验。


您在Dockerfile中将EXPOSE 8080与-p选项一起使用了吗?另外,请检查容器正在运行的盒子上的端口8080是否被安全规则所阻止。
keda

@keda是的,Dockerfile确实包含EXPOSE8080。我正在通过Docker的Quickstart Terminal在我的计算机上本地运行容器,我也尝试禁用Windows防火墙,但这都不起作用,我不知道是否有某些设置“M缺失
redsalt

Answers:


90

TL; DR检查VirtualBox主机的网络模式-是否应该bridged在本地网络上访问虚拟机(及其托管的Docker容器)。


听起来您的困惑在于连接到哪个主机以便通过HTTP访问您的应用程序。您还没有真正弄清楚您的配置是什么-基于您的标记中包含“ Windows”和“ VirtualBox”的事实,我将做出一些猜测。

我猜您在Windows主机上的VirtualBox中运行的某种Linux操作系统上运行了Docker。我将如下标记IP地址:

D = Docker容器的IP地址

L =在VirtualBox中运行的Linux主机的IP地址

W = Windows主机的IP地址

在Windows主机上运行Go应用程序时,可以http://W:8080/从本地网络上的任何位置连接到该应用程序。之所以可行,是因为Go应用程序绑定了Windows计算机上的端口8080,并且任何尝试访问IP地址上的端口8080的人都W将建立连接。

这就是它变得更加复杂的地方:

VirtualBox设置虚拟机(VM)时,可以以几种不同模式之一配置网络。我不记得所有不同的选项是什么,但是您想要的是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映像启动一个新容器,并将Linux主机(我的PC)上的端口8080转发(连接)到容器上的端口8080。Docker设置了自己的内部网络(具有自己的IP地址集),以允许Docker守护进程进行通信并允许容器相互通信。因此,基本上,您要做的-p 8080:8080就是将Docker的内部网络与“外部”网络连接-即。主机的网络适配器-在特定端口上。

到目前为止和我在一起?好的,现在让我们退后一步,看看您的系统。您的计算机正在运行Windows-Docker(当前)不在Windows上运行,因此您使用的工具已在VirtualBox虚拟机中设置了Linux主机。当你做docker run你的环境,同样的事情发生了- 8080端口在Linux主机上连接到端口8080的容器上。这里最大的区别是您的Windows主机不是运行容器的Linux主机,因此这里还有另一层,并且跨该层的通信会遇到问题。

您需要做的是以下两件事之一:

  1. 将VirtualBox VM上的端口8080连接到Windows主机上的端口8080,就像将Docker容器连接到主机端口一样。

  2. 使用上述bridged网络模式将VirtualBox VM直接连接到本地网络。

如果您选择第一个选项,则可以访问Windows主机的IP地址或主机名http://W:8080所在的容器W。如果选择第二个,则可以访问Linux VM的IP地址或主机名http://L:8080所在的容器L

这就是所有更高层次的说明-现在您需要弄清楚如何更改VirtualBox VM的配置。这是我无法真正为您提供帮助的地方-我不知道您使用什么工具在Windows机器上执行所有这些操作,而且我对在Windows上使用Docker一点也不熟悉。

如果可以进入VirtualBox配置窗口,则可以进行以下描述的更改。还有一个命令行客户端将修改VM,但是我对此并不熟悉。

对于bridged模式(这确实是最简单的选择),请关闭您的VM,单击顶部的“设置”按钮bridged,然后将网络模式更改为,然后重新启动VM,您就可以了。VM应该通过DHCP在本地网络上选择一个IP地址,并且对于该IP地址在网络上的其他计算机应该是可见的。


1
我只能找到2个IP,一个是Docker在打开快速入门终端(192.168.99.100)时显示的IP,另一个是我的计算机具有(192.168.0.157)的IP,使用docker run -p 8080:8080 dockertest我可以使用http://192.168.99.100:8080但只能从Windows计算机访问我的网站(主机),而不是通过我的手机。如果我使用docker run -p 192.168.0.157:8080:8080 dockertest,则无法从任何地方使用任何IP访问该网站。我不确定如何设置网络,我尝试使用过,--net=bridge但是那都不起作用。我应该打开VirtualBox吗?我不能使用Docker的终端吗?
redsalt

问题不在于Docker,所以不,Docker无法帮助您。我将添加一些编辑以说明我的想法。
Kryten

好的谢谢!现在我明白了,我对整个Linux虚拟机部分感到困惑。我给人的印象是Docker在使用Virtual Box来处理我不应该接触的内部内容。这实际上非常容易,我只需要bridged在Virtual Box中将其更改为,现在它就产生了奇迹,非常感谢。
redsalt

在同一个网络中没有任何办法可以容纳Windows和Docker容器,因此我们可以直接访问容器而无需端口转发?
Vituel '16

在docker中搜索正在运行的Jupyter服务器并尝试通过LAN访问它时偶然发现了这一点。无论如何,将模式切换为桥接后,我能找出L是什么吗?
PaulDong '16

121
  1. 打开Oracle VM VirtualBox Manager
  2. 选择Docker使用的VM
  3. 单击设置->网络
  4. 适配器1应该(默认?)为“附加到:NAT”
  5. 单击高级->端口转发
  6. 添加规则:协议TCP,主机端口8080,访客端口8080(将主机IP和访客IP保留为空)
  7. 来宾是您的Docker容器,而主机是您的机器

现在,您应该能够通过localhost:8080和your-internal-ip:8080浏览到您的容器。


10
确认,很好,很容易。
德克

2
最好的答案,没有巨大的描述等来选择一个
阿米尔·坎姆汗

2
对于无业游民的用户,请将其添加到无业游民的文件中:config.vm.network“ forwarded_port”,访客:8080,主机:8080,协议:“ tcp”
Vince Verhoeven

3
!这就像一个魅力!谢谢!!!!我花了几个小时试图弄清楚这一点。
Joseph Freeman

2
对于通过VBox运行Docker的任何人来说,这都是一个绝佳的解决方案!
Mirodinho

7

在尝试了几件事之后,这对我有用:

  • 使用--publish = 0.0.0.0:8080:8080 docker标志
  • 将virtualbox网络模式设置为NAT,并且不使用任何端口转发

使用除0.0.0.0我以外的地址均未成功。


4

TLDR:如果启用了Windows防火墙,请确保专用网络上的“ vpnkit”存在例外。

对于我的特定情况,当我尝试从本地网络上的另一台计算机访问容器的已发布端口时,我发现Windows防火墙正在阻止我的连接,因为禁用它可以使一切正常。

但是,我不想完全禁用防火墙,只是为了访问容器的服务。这就提出了一个问题,即哪个“ app”代表我的容器的服务在监听。找到另一个SO线程教我用来netstat -a -b发现机器上侦听套接字后面的应用程序后,我知道它是vpnkit.exe,它已经在Windows防火墙设置中包含一个条目:但是“专用网络”已被禁用,并且一旦启用它,便可以从另一台机器访问容器的服务,而不必完全禁用防火墙。


先生,您使我免于数小时的无奈。谢谢。
Behdad

2

这是Windows用户运行Docker容器时面临的最常见问题。IMO这是“关于Docker的百万美元问题”;@“ Rocco Smit”正确指出“入站流量,因为默认情况下它是在我的主机的防火墙上被禁用的”;就我而言,是我的McAfee Anti Virus软件。我在McAfee的“防火墙设置”中添加了其他端口,以允许来自同一Wifi LAN上其他计算机的入站流量;那是魔术。我花了一个多星期的时间浏览整个Internet,SO,Docker文档,与Docker Networking相关的教程后的教程,以及“ macvlan”,“ ipvlan”,“ user”的许多“ Windows上不支持”插图定义的网桥”甚至是相同的SO线程两次。我什至开始与“有人在生产中使用Docker吗?”浏览谷歌,(是的,我知道Linux在Prod工作负载中比Windows服务器更受欢迎),因为我无法从同一家庭wifi中的移动设备访问nginx。应用程序已部署在Windows的Docker容器中。毕竟,如果您至少不能从同一LAN中的其他计算机/设备访问应用程序(部署在Docker容器上),那有什么用?最终,就我而言,问题仅在于防火墙阻止了入站流量。如果您至少不能从同一LAN中的其他计算机/设备访问该应用程序(部署在Docker容器上);最终,就我而言,问题仅在于防火墙阻止了入站流量。如果您至少不能从同一LAN中的其他计算机/设备访问应用程序(部署在Docker容器上);最终,就我而言,问题仅在于防火墙阻止了入站流量。


0

我发现,与设置-p端口值一起,用于Windows的Docker使用vpnkit,并且默认情况下,在主机计算机的防火墙上禁用了vpnkit的入站流量。在为vpnkit启用入站TCP规则后,我能够从本地网络上的其他计算机访问我的容器。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.