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

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

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

docker run -p 8080:8080 dockertest

这个工作和 我可以通过 Docker 的机器 IP 进入服务器(一个出现在 码头快速启动终端启动时) ,问题是我 无法从主机外部访问我托管的网站,,所以如果我尝试打开相同的 IP 地址在我的手机上,它只是给我一个错误: 这个网页是不可用的(ERR _ CONNECTION _ TIMED _ OUT)。

我还尝试像这样指定 IP:

docker run -p 192.168.0.157:8080:8080 dockertest

但是,当我这样做,我可以访问网站,无论是通过多克机的 IP 或指定的 IP 上面的命令行。 我也不确定我应该在那个命令中写入哪个 IP,我用了我电脑的 IP,我也试过127.0.0.1(localhost) ,但是得到了同样的结果: 无论如何都不能通过任何 IP 访问网站。

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

此外,我可以在我的计算机上运行围棋代码,并通过我的计算机的 IP 从同一网络中的另一个设备访问网站。我不明白为什么我不能访问它时,我正在运行它在 Docker 机器,我突然想到,它可能有一些与 IP 转发或东西,但我是一个完全在网络菜鸟,我主要是一个网络开发人员,几乎没有经验在本地。

208773 次浏览

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


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.

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:

D = the IP address of the Docker container

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

W = the IP address of the Windows host

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 W will get connected.

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 bridged mode, 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.

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/.

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

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).

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 dockertest image 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:8080 is connecting Docker's internal networking with the "external" network - ie. the host's network adapter - on a particular port.

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 run in 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.

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 bridged network mode I described above.

If you go for the first option, you will be able to access the container at http://W:8080 where W is 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:8080 where L is the IP address or hostname of the Linux VM.

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.

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.

For bridged mode (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.

  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

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

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

With addresses other than 0.0.0.0 I had no success.

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.

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;

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

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.

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 thread that taught me to use netstat -a -b to 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.

I have tried lots of things but nothing worked, then finally i accessed the docker host using IP address of my machine Follow the step

  1. Open the CMD
  2. IPCONFIG /ALL
  3. Look for the IPV4 address, in my case its 192.168.1.7
  4. Then I accessed the app hosted in docker container with mapped port
  5. In my case i tried to access my Jenkins application hosted as a container
  6. Simply it worked 192.168.1.7:50000
  7. In the same way I am able to access all container apps hosted using docker

Based on the Kryten answer - I will add a little information about the configuration in Windows.

  1. Stop the Virtual Machine
  2. Open VM settings -> Network -> tab "Adapter 3":
  • check "Enable Network Adapter"
  • Attached to: "Bridged Adapter".
  • name: [your windows network adapter]

Screenshot