Docker on OSX: Port Forwarding

If you’ve tried to run Docker 0.8 on OSX, you know that everything works great except for port forwarding. Have no fear, here is your guide to getting port forwarding working for Docker on OSX:

Step 1. Export the port in your container

First, you should make sure to expose the port in the image you are running. If you are using a pre-built image this is usually taken care of for you, but if you are building an image yourself from a Dockerfile you need to add the following line near the end:

EXPOSE 80

The EXPOSE command exposes port 80 to the external of the container (If you need to expose a different port just use that instead of 80). Then, when launching the container based on this image be sure to specify the port binding you would like to use:

docker run -n -p 80:80 -d YOUR_IMAGE

The -p option tells docker to bind port 80 on the host (your laptop) to port 80 in the container (which we exposed in the image).

Normally, on pure linux systems, you would now be able to connect to the container on port 80. On OSX this isn’t the case.

Step 2. Configure VirtualBox 

Docker 0.8 for OSX relies on boot2docker which in turn uses VirtualBox to host the VM that runs the linux OS to run the containers. Unfortunately, despite the fact that you have told Docker to forward ports, VirtualBox doesn’t know about your port forwarding intentions and is blocking connections. You need to open up port forwarding in VirtualBox as well by running the following command:

VBoxManage modifyvm "boot2docker-vm" --natpf1 "guestnginx,tcp,,80,,80"

This uses the VirtualBox command line interface to update the boot2docker virtual machine to forward everything from port 80 on your laptop to port 80 in the virtual machine which will then, in turn, be available to your containers. –natpf1 specifies the first virtual network device of the VM handles the forwarding, but that is not an important detail.

Now you should be able to reach your container on port 80!

Conclusion

While this does work, it is very inconvenient if you run many containers using many different ports. It is a side effect of OSX not supporting containers natively, requiring another OS layer between you and your containers. Unfortunately boot2docker cannot take care of this for you since it doesn’t know what ports you need when you are getting started and once the Docker daemon is running in the virtual machine it cannot be modified.

Until there is a better solution, I recommend using a linux machine for most of your container testing and only using your OSX laptop for development testing.

Advertisements

13 thoughts on “Docker on OSX: Port Forwarding

  1. There is indeed a better solution we are looking at via host only networking. Look at PR #93, once it’s merged, you will be fine 😉

  2. Yes, in fact I’ve set it up to forward 4 ports on my laptop since I have a few containers each of which uses a different port.

    But remember that if you run that port forwarding command, the VM will occupy that port even if there is no container listening. Hence, if you assign port 80 to the VM, as long as the VM is running you can’t do anything else on port 80 on your laptop even if you have no containers running.

  3. I’d also recommend using the host only interface rather than VirtualBox port forwarding. The reason is that (at least the OSX) VirtualBox NAT implementation doesn’t properly support half-closes of inbound TCP connections. This can cause problems like truncated output from commands like:

    docker run busybox sh -c ‘echo 01234; sleep 1; echo 56789’

    It took me a while to work out that VirtualBox’s NAT implementation was at fault. I wrote uo my findings here, complete with a independent of Docker, test case:

    https://github.com/jonseymour/vbox-portforward

    The underlying VirtualBox issue is documented here: https://www.virtualbox.org/ticket/13116

  4. I cannot get port 80 to forward to Vbox on my Mac OS X 9.5… 8080 works fine though. Is it because I cannot use ports under 1024 unless VBox runs as root user?

  5. Thanks Sean! That’s a very helpful post. I ended up following this guide to set up 2 VirtualBox network adapters. One with typical NAT and a second one with hostguest communication. Now I can simply do curl http://192.168.56.101/ (over port 80) and it works normally. The advantage is that I only need to configure this one time, and all future services on any port will work automatically just by connecting to the IP address.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s