128

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.

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:

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

I've also tried specifying the IP like this:

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.

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.

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.

2
  • did you use EXPOSE 8080 in your Dockerfile in conjunction with the -p option? Also, check to see that port 8080 on the box there your container is running isn't blocked by your security rules. Commented Nov 19, 2015 at 21:40
  • @keda Yes, the Dockerfile does contain EXPOSE 8080. I'm running the container locally on my computer through Docker's Quickstart Terminal, I also tried disabling Windows firewall but that didn't work neither, I don't know if there's some setting I'm missing Commented Nov 20, 2015 at 3:20

9 Answers 9

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

Sign up to request clarification or add additional context in comments.

4 Comments

guest port is the container port number which you want to access. For example you have django running on port 8000 on your container, so you guest port will be 8000. Host port is the port number which you will use to access from another machine or browser.
The only one that worked after hours of research! Really grateful Davey. Just a further comment to confirm that using docker-toolbox, often docker port is something like 32768 or 95786 etc. That is the port to be set in Port Forwarding. Therefore it will be something like localhost:32768 and your-internal-ip:32768.
for vagrant users add this in vagrantfile: config.vm.network "forwarded_port", guest: 8080, host: 8080, protocol: "tcp"
This is only a work around, if we have multiple application in container then we have to do multiple port forwarding
107

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.

2 Comments

Isn't there any way to have windows and docker containers in the same network, so we could access containers directly without port forwarding?
When I change to bridge it is indefinitely waiting to get an IP address.
8

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.

Comments

5

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.

2 Comments

Thanks for the netstat trick. For me, it wasnt vpnkit, but C:\program files\docker\docker\resources\com.docker.backend.exe. It had to be created as an outbound rule (it already existed as inbound rule)
This seems to repeat the solution from Rocco Smit's answer from 4 months prior ("your firewall might be blocking the traffic").
3

Rocco Smit's answer rightly pointed out

inbound traffic for it was disabled by default on my host machine's firewall

In my case, this was caused by my McAfee 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 worked.

1 Comment

This just repeats the solution from Rocco Smit's answer, which is that your firewall was blocking traffic. Please only post new answers if you have new solutions to provide.
1

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.

Comments

1

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

2 Comments

Does it work, if I (or someone else) want to use the Jenkins running on your machine as a docker container?
Yes if your machine has public static IP configured, but the one is shown is a local IP..
1

Adding a little information about the configuration in Windows based on Kryten's answer:

  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

Comments

-1

For Docker Desktop 4.46.0 (204649), basically the only thing required is to allow the port you want to use through the firewall with an inbound rule.

Using PowerShell (run as administrator).

# For port 80 (HTTP) New-NetFirewallRule -DisplayName "Port 80" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 80 # For port 443 (HTTPS) New-NetFirewallRule -DisplayName "Port 443" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 443 # For custom ports (e.g., 8080) New-NetFirewallRule -DisplayName "Port 8080" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 8080 

Or in the Command Prompt (run as administrator).

netsh advfirewall firewall add rule name="Port 80 LAN Access" dir=in action=allow protocol=TCP localport=80 netsh advfirewall firewall add rule name="Port 443 LAN Access" dir=in action=allow protocol=TCP localport=443 netsh advfirewall firewall add rule name="Port 8080 LAN Access" dir=in action=allow protocol=TCP localport=8080 

1 Comment

This question is specific to Oracle's VirtualBox environment. If you have a similar situation on a different environment/software platform, and want to share that info, post it in an existing question for that platform, or post you're own self-answered Q&A.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.