At work, I needed to run a Docker container with a Rails application that talked to another application running inside a VMWare virtual machine. Adding to the complexity, I use boot2docker, which runs inside of VirtualBox.
If I only needed to access
api.localdomain.dev from my Mac, I could have simply edited
/etc/hosts and set both domains to resolve to
127.0.0.1 and been
done with it. Unfortunately, Rails needed to be able to directly
resolve the API server.
Setting up dnsmasq
NOTE: It’s possible that editing
/etc/hosts would have been
enough and I didn’t need to set up dnsmasq at all. Read the section
about configuring the virtual machine’s DNS first.
Our Rails application must run at a domain like
rails.localdomain.dev, and the API server runs at
api.localdomain.dev, so I configured dnsmasq to manage the
I moved the hard-coded DNS entry for
dnsmasq.conf. I found this IP by logging into the
API VM and looking at the output of
ifconfig. I’m not certain why
this IP will not change, but that’s what I was told.
Creating a routable “loopback address”
Originally, I had configured
api.localdomain.dev to resolve to
127.0.0.1. This works fine when accessed from the Mac, but when a
virtual machine resolved that domain,
127.0.0.1 would refer to the
virtual machine itself! I needed an IP address that:
- Would refer to my laptop.
- Wouldn’t change when I changed network configuration.
- Wouldn’t resolve to the VM inside the VM.
We can accomplish this by using an ifconfig
10.254.254.254 because it is a private network
address and it is unlikely to be used on any networks I connect to. If
I ever do have a conflict, there are many other private addresses to
dnsmasq.conf and replaced
10.254.254.254. Requests for
*.localdomain.dev will now resolve to
an IP address that will always refer to the Mac, but that the virtual
machines will not think resolves to the virtual machine itself.
Big thanks to Andre for helping me find and understand how aliasing works!
Configuring virtual machine DNS
Next I configured the virtual machine to route all DNS requests through the Mac’s resolving system. For VirtualBox, configure it according to this serverfault answer. If you are using Vagrant, you can add a stanza like:
1 2 3 4 5
I’m not sure, but it’s possible that these settings would use entries
configured in my Mac’s
/etc/hosts. This could make it so that the
dnsmasq step isn’t required.
Instead of resolving through the host, I could have edited
/etc/resolv.conf and used
10.254.254.254 as my DNS server
instead. If you do this, you definitely need to run dnsmasq.
Once the virtual machine could ping
api.localdomain.dev, I restarted
the Docker daemon to pick up the networking changes. Dropping into a
Docker container, I was able to ping the API server as well. Success!