如何从主机外部(同一网络)连接到 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 主机,所以这里还有另一层,它是跨你所在层的通信 运行遇到问题。
您需要的是以下两种情况之一:
将 VirtualBox VM 上的端口 8080 连接到 Windows 主机上的端口 8080,就像将 Docker 容器连接到主机端口一样。
使用我上面描述的 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 地址的网络上的其他计算机应该可见。
- 打开 Oracle VM VirtualBox 管理器
- Select Docker
使用的虚拟机
- 点击设置 -> 网络
- 适配器 1 应该(默认?)是 "Attached to: NAT"
- 点击高级 -> 端口转发
- 添加规则:协议 TCP,主机端口 8080,访客端口 8080(主机 IP 和访客 IP 留空)
- 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 主机
按照步骤
- 打开CMD
- IP配置/全部
- 查找 IPV4 地址,在我的例子中是 192.168.1.7
- 然后我使用映射端口
访问了托管在docker容器中的应用程序
- 就我而言,我尝试访问作为容器托管的 Jenkins 应用程序
- 简单地说它有效 192.168.1.7:50000
- 以同样的方式,我能够访问使用 docker
托管的所有容器应用程序
我已经创建了我的第一个 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
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/
.
如果 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 主机,所以这里还有另一层,它是跨你所在层的通信 运行遇到问题。
您需要的是以下两种情况之一:
将 VirtualBox VM 上的端口 8080 连接到 Windows 主机上的端口 8080,就像将 Docker 容器连接到主机端口一样。
使用我上面描述的
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 地址的网络上的其他计算机应该可见。
- 打开 Oracle VM VirtualBox 管理器
- Select Docker 使用的虚拟机
- 点击设置 -> 网络
- 适配器 1 应该(默认?)是 "Attached to: NAT"
- 点击高级 -> 端口转发
- 添加规则:协议 TCP,主机端口 8080,访客端口 8080(主机 IP 和访客 IP 留空)
- 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 主机 按照步骤
- 打开CMD
- IP配置/全部
- 查找 IPV4 地址,在我的例子中是 192.168.1.7
- 然后我使用映射端口 访问了托管在docker容器中的应用程序
- 就我而言,我尝试访问作为容器托管的 Jenkins 应用程序
- 简单地说它有效 192.168.1.7:50000
- 以同样的方式,我能够访问使用 docker 托管的所有容器应用程序