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

How to connect to a docker container from outside the host (same network) [Windows]

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

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

docker run -p 8080:8080 dockertest

有效,我可以通过 docker 的机器 IP 访问服务器(显示在 Docker Quickstart Terminal 启动时),问题是我 无法从主机外部访问我托管的网站, 所以如果我尝试打开相同的 IP我 phone 上的地址只是给我一个错误:此网页不可用 (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) 但这给了我相同的结果:无法通过任何方式访问该网站任何IP。

我用谷歌搜索了这个问题,发现了很多 Whosebug 问题,但都没有帮助我解决我的问题,其中大部分都是面向 Linux 或 Mac,所以该解决方案不适用于我的问题情况。

另外,我可以运行我电脑上的Go代码,通过我电脑的IP从同一网络中的另一台设备访问该网站。我不明白为什么我在 运行 机器上 运行 时无法访问它,我想到它可能与 IP 转发或其他东西有关,但我我是网络方面的菜鸟,我主要是一名 Web 开发人员,几乎没有本地经验。

TL;DR 检查你的 VirtualBox 主机的网络模式 - 如果你想要虚拟机(和 Docker 容器,它应该是 bridged它正在托管)可在您的本地网络上访问。


听起来您的困惑在于连接到哪个主机以便通过 HTTP 访问您的应用程序。您还没有真正说明您的配置是什么 - 我将根据您的标签中包含 "Windows" 和 "VirtualBox" 的事实进行一些猜测。

我猜您在 Windows 主机上的 VirtualBox 中 Docker 运行ning 有点 Linux 运行ning 的风格。我将按如下方式标记 IP 地址:

D = Docker 容器的 IP 地址

L = Linux主机运行ning在VirtualBox

中的IP地址

W = Windows 主机的 IP 地址

当您 运行 您的 Windows 主机上的 Go 应用程序时,您可以从本地网络的任何位置使用 http://W:8080/ 连接到它。这是可行的,因为 Go 应用程序绑定了 Windows 机器上的端口 8080,任何试图访问 IP 地址 W 上的端口 8080 的人都将获得连接。

这里是变得更复杂的地方:

VirtualBox 在设置虚拟机 (VM) 时,可以以多种不同模式之一配置网络。我不记得所有不同的选项是什么,但你想要的是 bridged。在这种模式下,VirtualBox 将虚拟机连接到您的本地网络,就好像它是网络上的独立机器一样,就像插入网络的任何其他机器一样。在 bridged 模式下,虚拟机像任何其他机器一样出现在您的网络上。其他模式设置不同,机器在您的网络上不可见。

因此,假设您为 Linux 主机 (bridged) 正确设置了网络,Linux 主机将在您的本地网络上有一个 IP 地址(类似于 192.168. 0.x),您将能够在 http://L:8080/.

访问您的 Docker 容器

如果 Linux 主机设置为 bridged 以外的模式,您 可能 能够从 Windows 主机访问, 但这将取决于它所处的模式。

编辑 - 根据下面的评论,我上面描述的情况听起来很正确。

让我们回顾一下:这是 Docker 在我的计算机上的工作方式 (Ubuntu Linux)。

假设我 运行 与您有相同的命令:docker run -p 8080:8080 dockertest。这样做是基于 dockertest 图像启动一个新容器,并将 Linux 主机(我的 PC)上的端口 8080 转发(连接)到容器上的端口 8080。 Docker 设置自己的内部网络(使用自己的一组 IP 地址)以允许 Docker 守护程序进行通信并允许容器相互通信。所以基本上你用 -p 8080:8080 做的是将 Docker 的内部网络连接到 "external" 网络 - 即。主机的网络适配器 - 在特定端口上。

到现在为止?好的,现在让我们退后一步,看看您的系统。您的机器 运行ning Windows - Docker 不(当前)运行 Windows,因此您使用的工具已经设置了 Linux VirtualBox 虚拟机中的主机。当您在您的环境中执行 docker run 时,会发生完全相同的事情 - Linux 主机上的端口 8080 连接到容器上的端口 8080。这里最大的不同是你的 Windows 主机不是容器 运行ning 所在的 Linux 主机,所以这里还有另一层,它是跨你所在层的通信 运行遇到问题。

您需要的是以下两种情况之一:

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

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

如果选择第一个选项,您将能够访问位于 http://W:8080 的容器,其中 W 是 Windows 主机的 IP 地址或主机名。如果您选择第二种,您将能够访问位于 http://L:8080 的容器,其中 L 是 Linux VM 的 IP 地址或主机名。

这就是所有更高级别的解释 - 现在您需要弄清楚如何更改 VirtualBox VM 的配置。这就是我无法真正帮助你的地方——我不知道你用什么工具在你的 Windows 机器上完成所有这些,而且我一点也不熟悉在 Docker 上使用Windows.

如果可以访问 VirtualBox 配置 window,则可以进行如下所述的更改。还有一个命令行客户端可以修改虚拟机,但我不熟悉。

对于 bridged 模式(这确实是最简单的选择),关闭您的 VM,单击顶部的 "Settings" 按钮,并将网络模式更改为 bridged ,然后重新启动虚拟机,一切顺利。 VM 应通过 DHCP 在您的本地网络上获取一个 IP 地址,并且该 IP 地址的网络上的其他计算机应该可见。

  1. 打开 Oracle VM VirtualBox 管理器
  2. Select Docker
  3. 使用的虚拟机
  4. 点击设置 -> 网络
  5. 适配器 1 应该(默认?)是 "Attached to: NAT"
  6. 点击高级 -> 端口转发
  7. 添加规则:协议 TCP,主机端口 8080,访客端口 8080(主机 IP 和访客 IP 留空)
  8. Guest 是您的 docker 容器,Host 是您的机器

您现在应该能够通过 localhost:8080 和您的内部 IP:8080 浏览到您的容器。

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

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

使用 0.0.0.0 以外的地址我没有成功。

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

这是 Windows 用户在 运行 Docker 容器中面临的最常见问题。国际海事组织这是 "million dollar question on Docker"; @"Rocco Smit" 正确地指出了 "inbound traffic for it was disabled by default on my host machine's firewall";就我而言,我的 McAfee Anti Virus 软件。我在 McAfee 的防火墙设置中添加了额外的端口,以允许来自同一 Wifi LAN 上其他计算机的入站流量;然后它是神奇的。我花了一个多星期的时间浏览整个互联网,SO,Docker 文档,与 Docker 的网络相关的教程之后的教程,以及 "not supported on Windows" for [=16] 的许多插图=]、"ipvlan"、"user defined bridge" 甚至同一个 SO 线程几次。我什至开始用 "anybody using Docker in Production?" 浏览 google,(是的,我知道 Linux 比 Windows 服务器更适合 Prod 工作负载)因为我无法访问(从我的在同一个家庭 wifi 中移动)部署在 Windows 上的 Docker 容器中的 nginx 应用程序。毕竟,如果您至少无法从同一 LAN 中的其他计算机/设备访问应用程序(部署在 Docker 容器上),这有什么好处;最终就我而言,问题只是防火墙阻止了入站流量;

TLDR: 如果您启用了 Windows 防火墙,请确保私有网络上的 "vpnkit" 例外。

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

但是,我不想完全禁用防火墙只是为了访问容器的服务。这引出了 "app" 代表我的容器服务监听的问题。在找到 another SO thread 教我使用 netstat -a -b 发现我机器上监听套接字背后的应用程序后,我了解到它是 vpnkit.exe,它已经在我的 [=24] 中有一个条目=] 防火墙设置:但是 "private networks" 被禁用了,一旦我启用它,我就可以从另一台机器访问我的容器服务,而不必完全禁用防火墙。

我尝试了很多方法但都没有用,最后我使用我机器的 IP 地址访问了 docker 主机 按照步骤

  1. 打开CMD
  2. IP配置/全部
  3. 查找 IPV4 地址,在我的例子中是 192.168.1.7
  4. 然后我使用映射端口
  5. 访问了托管在docker容器中的应用程序
  6. 就我而言,我尝试访问作为容器托管的 Jenkins 应用程序
  7. 简单地说它有效 192.168.1.7:50000
  8. 以同样的方式,我能够访问使用 docker
  9. 托管的所有容器应用程序