If you have been following my posts on Docker then you know by now that I
usually run on OSX with
Boot2Docker. It is definitely a
really useful tool if you are not on a native Linux kernel and it makes using
Docker on Mac and Windows almost as easy and transparent as if you were on Linux.
That is, until you need to expose one or more ports from your containers and
then you want to access those from your host. If you are on Linux then you can
simply go to
localhost and the port number and that’s it. If you are using
boot2docker however, you need to remember that your docker host is actually the
boot2docker VM and not your laptop, so you first need to know what that VM’s IP
is. In this very short post I want to describe a way in which you can access
your containers on
localhost even if you are using boot2docker.
The important thing to know is that boot2docker is a Virtual Machine that runs
on Virtual Box. And as with any other VM you can forward ports between your host
and guest operating system. That means that if we can get Virtual Box to forward
whatever port we expose from our containers, from our host OS to the boot2docker
VM then those ports will be accessible from our
So how can we do that? I don’t really know if this works on Windows (I assume it
does) but on Mac you can use the
VBoxManage command line tool to control the
different VMs that Virtual Box manages.
So let’s imagine that our Nginx container exposes port 80 and then we map that
to port 8080 on the VM when we do a
docker run -p 8080:80. Normally you would
be able to access this by going to
http://$DOCKER_IP:8080. But with VBoxManage
you can do:
VBoxManage controlvm boot2docker-vm natpf1 "nginx,tcp,127.0.0.1,8080,,8080".
This basically means: “Take the boot2docker-vm and create a new NAT rule called
nginx that will forward all requests on the localhost (127.0.0.1) port 8080 to
port 8080 on the VM”.
Now we can access our container on
http://localhost:8080. Simple as that! Best
of all is that you can do this while the VM and your containers are running and
doesn’t require you to restart anything.
When you are done and you want to delete the NAT rule you can just do
VBoxManage controlvm boot2docker-vm natpf1 delete "nginx".
But why would you do this?
$DOCKER_IP instead of
localhost makes little to no
difference. In fact, if you count the time it takes you to do the
stuff then it is probably slower.
In the case when you are just playing around with different containers and want
to test things locally I agree that this makes no sense. But sometimes it can be
Imagine for instance that you are developing a webapp. You run all the backend
services that your app needs as docker containers and then you just run the
frontend part in your laptop, pointing to these containers.
If you are developing on Mac then you would have to point your webapp to
$DOCKER_IP but if then you move to Ubuntu for instance, you would need to change
all places where you were previously using $DOCKER_IP to use localhost instead.
In this scenario, creating a little script that runs the containers and then
VBoxManage to forward the exposed ports can give you better portability
between different platforms.
In any case, whether you find a good use case for it or not it is still good to know that you have that option if you ever need it. The rest is up to you!