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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33814696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 19:21:01  来源:igfitidea点击:

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

windowsdockervirtualbox

提问by redsalt

I've created my first docker container, it's running a server using Go but I can't access it from outside the host computer. I've just started with docker so I'm a little lost here.

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

So I have a very simple Go code that starts a server, I have built the docker image which installs Go and builds the code in a Linux base image. I'm running the server on port 8080 so I expose that port to the host running the container like this:

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

docker run -p 8080:8080 dockertest

That works and I get to access the server through docker's machine IP(the one that appears on the Docker Quickstart Terminalwhen initiated), the problem is I can't access the website I'm hosting from outside the host,so if I try to open the same IP address on my phone it just gives me an error: This webpage is not available (ERR_CONNECTION_TIMED_OUT).

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

I've also tried specifying the IP like this:

我也试过像这样指定 IP:

docker run -p 192.168.0.157:8080:8080 dockertest

But when I do that I can access the website through neither the docker machine's IP nor the specified IP on the command line above. I'm also not sure which IP I'm supposed to write in that command I used my computer's IP, I've also tried 127.0.0.1 (localhost) but that gave me the same result: couldn't access the website through any IP whatsoever.

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

I've googled this problem and found many StackOverflow questions but neither helped me solve my issue, most of them were oriented to Linux or Mac so the solution didn't apply to my situation.

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

Also, I can run the Go code on my computer and access the website from another device in the same network through my computer's IP. I don't understand why I can't access it when I'm running it in the docker machine, it occurred to me that it may have something to do with IP forwarding or something but I'm a complete noob in networking, I'm mostly a web developer and have almost no experience in native.

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

回答by Davey Chu

  1. Open Oracle VM VirtualBox Manager
  2. Select the VM used by Docker
  3. Click Settings -> Network
  4. Adapter 1 should (default?) be "Attached to: NAT"
  5. Click Advanced -> Port Forwarding
  6. Add rule: Protocol TCP, Host Port 8080, Guest Port 8080 (leave Host IP and Guest IP empty)
  7. Guest is your docker container and Host is your machine
  1. 打开 Oracle VM VirtualBox 管理器
  2. 选择Docker使用的VM
  3. 点击设置->网络
  4. 适配器 1 应该(默认?)是“附加到:NAT”
  5. 点击高级 -> 端口转发
  6. 添加规则:Protocol TCP、Host Port 8080、Guest Port 8080(Host IP和Guest IP留空)
  7. Guest 是你的 docker 容器,Host 是你的机器

You should now be able to browse to your container via localhost:8080 and your-internal-ip:8080.

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

回答by Kryten

TL;DRCheck the network mode of your VirtualBox host - it should be bridgedif you want the virtual machine (and the Docker container it's hosting) accessible on your local network.

TL;DR检查您的 VirtualBox 主机的网络模式 -bridged如果您希望虚拟机(及其托管的 Docker 容器)可在您的本地网络上访问,则应该这样做。



It sounds like your confusion lies in which host to connect to in order to access your application via HTTP. You haven't really spelled out what your configuration is - I'm going to make some guesses, based on the fact that you've got "Windows" and "VirtualBox" in your tags.

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

I'm guessing that you have Docker running on some flavour of Linux running in VirtualBox on a Windows host. I'm going to label the IP addresses as follows:

我猜你在 Windows 主机上的 VirtualBox 中运行了某种 Linux 版本的 Docker。我将按如下方式标记 IP 地址:

D= the IP address of the Docker container

D= Docker 容器的 IP 地址

L= the IP address of the Linux host running in VirtualBox

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

W= the IP address of the Windows host

W= Windows 主机的 IP 地址

When you run your Go application on your Windows host, you can connect to it with http://W:8080/from anywhere on your local network. This works because the Go application binds the port 8080 on the Windows machine and anybody who tries to access port 8080 at the IP address Wwill get connected.

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

And here's where it becomes more complicated:

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

VirtualBox, when it sets up a virtual machine (VM), can configure the network in one of several different modes. I don't remember what all the different options are, but the one you want is bridged. In this mode, VirtualBox connects the virtual machine to your local network as if it were a stand-alone machine on the network, just like any other machine that was plugged in to your network. In bridgedmode, the virtual machine appears on your network like any other machine. Other modes set things up differently and the machine will not be visible on your network.

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

So, assuming you set up networking correctly for the Linux host (bridged), the Linux host will have an IP address on your local network (something like 192.168.0.x) and you will be able to access your Docker container at http://L:8080/.

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

If the Linux host is set to some mode other than bridged, you mightbe able to access from the Windows host, but this is going to depend on exactly what mode it's in.

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

EDIT- based on the comments below, it sounds very much like the situation I've described above is correct.

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

Let's back up a little: here's how Docker works on my computer (Ubuntu Linux).

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

Imagine I run the same command you have: docker run -p 8080:8080 dockertest. What this does is start a new container based on the dockertestimage and forward (connect) port 8080 on the Linux host (my PC) to port 8080 on the container. Docker sets up it's own internal networking (with its own set of IP addresses) to allow the Docker daemon to communicate and to allow containers to communicate with one another. So basically what you're doing with that -p 8080:8080is connecting Docker's internal networking with the "external" network - ie. the host's network adapter - on a particular port.

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

With me so far? OK, now let's take a step back and look at your system. Your machine is running Windows - Docker does not (currently) run on Windows, so the tool you're using has set up a Linux host in a VirtualBox virtual machine. When you do the docker runin your environment, exactly the same thing is happening - port 8080 on the Linux host is connected to port 8080 on the container. The big difference here is that your Windows host is not the Linux host on which the container is running, so there's another layer here and it's communication across this layer where you are running into problems.

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

What you need is one of two things:

你需要的是两件事之一:

  1. to connect port 8080 on the VirtualBox VM to port 8080 on the Windows host, just like you connect the Docker container to the host port.

  2. to connect the VirtualBox VM directly to your local network with the bridgednetwork mode I described above.

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

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

If you go for the first option, you will be able to access the container at http://W:8080where Wis the IP address or hostname of the Windows host. If you opt for the second, you will be able to access the container at http://L:8080where Lis the IP address or hostname of the Linux VM.

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

So that's all the higher-level explanation - now you need to figure out how to change the configuration of the VirtualBox VM. And here's where I can't really help you - I don't know what tool you're using to do all this on your Windows machine and I'm not at all familiar with using Docker on Windows.

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

If you can get to the VirtualBox configuration window, you can make the changes described below. There is also a command line client that will modify VMs, but I'm not familiar with that.

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

For bridgedmode (and this really is the simplest choice), shut down your VM, click the "Settings" button at the top, and change the network mode to bridged, then restart the VM and you're good to go. The VM should pick up an IP address on your local network via DHCP and should be visible to other computers on the network at that IP address.

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

回答by mnieber

After trying several things, this worked for me:

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

  • use the --publish=0.0.0.0:8080:8080 docker flag
  • set the virtualbox network mode to NAT, and don't use any port forwarding
  • 使用 --publish=0.0.0.0:8080:8080 docker 标志
  • 将 virtualbox 网络模式设置为 NAT,并且不使用任何端口转发

With addresses other than 0.0.0.0I had no success.

除了0.0.0.0我以外的地址没有成功。

回答by Atul Varma

TLDR:If you have Windows Firewall enabled, make sure that there is an exception for "vpnkit" on private networks.

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

For my particular case, I discovered that Windows Firewall was blocking my connection when I tried visiting my container's published port from another machine on my local network, because disabling it made everything work.

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

However, I didn't want to disable the firewall entirely just so I could access my container's service. This begged the question of which "app" was listening on behalf of my container's service. After finding another SO threadthat taught me to use netstat -a -bto discover the apps behind the listening sockets on my machine, I learned that it was vpnkit.exe, which already had an entry in my Windows Firewall settings: but "private networks" was disabled on it, and once I enabled it, I was able to visit my container's service from another machine without having to completely disable the firewall.

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

回答by banarasi

This is the most common issue faced by Windows users for running Docker Containers. IMO this is the "million dollar question on Docker"; @"Rocco Smit" has rightly pointed out "inbound traffic for it was disabled by default on my host machine's firewall"; in my case, my McAfee Anti Virus software. I added additional ports to be allowed for inbound traffic from other computers on the same Wifi LAN in the Firewall Settings of McAfee; then it was magic. I had struggled for more than a week browsing all over internet, SO, Docker documentations, Tutorials after Tutorials related to the Networking of Docker, and the many illustrations of "not supported on Windows" for "macvlan", "ipvlan", "user defined bridge" and even this same SO thread couple of times. I even started browsing google with "anybody using Docker in Production?", (yes I know Linux is more popular for Prod workloads compared to Windows servers) as I was not able to access (from my mobile in the same Home wifi) an nginx app deployed in Docker Container on Windows. After all, what good it is, if you cannot access the application (deployed on a Docker Container) from other computers / devices in the same LAN at-least; Ultimately in my case, the issue was just with a firewall blocking inbound traffic;

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

回答by Rocco Smit

I found that along with setting the -p port values, Docker for Windows uses vpnkit and inbound traffic for it was disabled by default on my host machine's firewall. After enabling the inbound TCP rules for vpnkit I was able to access my containers from other machines on the local network.

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