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 rails.localdomain.dev
or
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.
I followed this tutorial to install and configure dnsmasq. You can ignore the parts about nginx and foreman.
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
.localdomain.dev
domain.
I moved the hard-coded DNS entry for api.localdomain.dev
from
/etc/hosts
to 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 alias
:
1
|
|
I picked 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
choose from!
I edited dnsmasq.conf
and replaced 127.0.0.1
with
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!