How to connect to a docker container from outside the host (same network) [Windows]
- Open Oracle VM VirtualBox Manager
- Select the VM used by Docker
- Click Settings -> Network
- Adapter 1 should (default?) be "Attached to: NAT"
- Click Advanced -> Port Forwarding
- Add rule: Protocol TCP, Host Port 8080, Guest Port 8080 (leave Host IP and Guest IP empty)
- 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.
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:
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.
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.
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.
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.
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;