There is a known issue with Docker for Mac, “.localhost DNS doesn’t resolve in browsers other than Chrome“. Docker4Drupal talks about it here and Træfik has a thread here. I found using Dnsmasq a better solution for me than editing the hosts file for each project I work with.
Adapted and edited from Using Dnsmasq for local development on OS X – Thomas Sutton
Most web developers will be familiar with the process of updating your
/etc/hosts file to direct traffic for
127.0.0.1. Most will also be familiar with the problems of this approach:
- it requires a configuration change every time you add or remove a project; and
- it requires administration access to make the change.
Installing a local DNS server like Dnsmasq and configuring your system to use that server can make these configuration changes a thing of the past. In this post, I’ll run through the process of:
- Installing Dnsmasq on OS X.
- Configuring Dnsmasq to respond to all
- Configure OS X to send all
.docker.localhostrequests requests to Dnsmasq.
Before we get started, I should give you a warning: these instructions show you how to install new system software and change your system configuration. Like all such changes, you should not proceed unless you are confident you have understood them and that you can reverse the changes if needed.
To quote the Dnsmasq project home page
There are plenty of ways to install Dnsmasq but my favourite (on OS X) is to use the Homebrew package manager. Installing Homebrew is fairly simple but beyond my scope here.
Once you have Homebrew installed, using it to install Dnsmasq is easy:
# Update your homebrew installation brew up # Install dnsmasq brew install dnsmasq
The installation process will output several commands that you can use to start Dnsmasq automatically with a default configuration. I used the following commands but you should use whichever commandsbrew tells you to:
# Copy the default configuration file. cp $(brew list dnsmasq | grep /dnsmasq.conf.example$) /usr/local/etc/dnsmasq.conf # Copy the daemon configuration file into place. sudo cp $(brew list dnsmasq | grep /homebrew.mxcl.dnsmasq.plist$) /Library/LaunchDaemons/ # Start Dnsmasq automatically. sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
Now that you have Dnsmasq installed and running, it’s time to configure it! The configuration file lives at
/usr/local/etc/dnsmasq.conf by default, so open this file in your favourite editor.
One the many, many things that Dnsmasq can do is compare DNS requests against a database of patterns and use these to determine the correct response. I use this functionality to match any request which ends in
.docker.localhost and send
127.0.0.1 in response. The Dnsmasq configuration directive to do this is very simple:
Insert this into your/usr/local/etc/dnsmasq.conf
file (I put it near the exampleaddress=/double-click.net/127.0.0.1 entry just to keep them all together) and save the file.
You may need to restart Dnsmasq to get it to recognise this change. Restarting Dnsmasq is the same as any other service running under
sudo launchctl stop homebrew.mxcl.dnsmasq sudo launchctl start homebrew.mxcl.dnsmasq
You can test Dnsmasq by sending it a DNS query using thedig
utility. Pick a name ending indocker.localhost and use dig to query your new DNS server:
dig testing.testing.one.two.three.docker.localhost @127.0.0.1
You should get back a response something like:
;; ANSWER SECTION: testing.testing.one.two.three.docker.localhost. 0 IN A 127.0.0.1
Configuring OS X
.docker.localhost queries to Dnsmasq.
Most UNIX-like operating systems have a configuration file called
/etc/resolv.conf which controls the way DNS queries are performed, including the default server to use for DNS queries (this is the setting that gets set automatically when you connect to a network or change your DNS server/s in System Preferences).
OS X also allows you to configure additional resolvers by creating configuration files in the
/etc/resolver/ directory. This directory probably won’t exist on your system, so your first step should be to create it:
sudo mkdir -p /etc/resolver
Now you should create a new file in this directory for each resolver you want to configure. Each resolver corresponds – roughly and for our purposes – to a top-level domain like ourdev. There a number of details you can configure for each resolver but I generally only bother with two:
- the name of the resolver (which corresponds to the domain name to be resolved); and
- the DNS server to be used.
For more information about these files, see the
resolver(5) manual page:
Create a new file with the same name as your new top-level domain (I’m using
docker.localhost, recall) in the
/etc/resolver/ directory and add a
nameserver to it by running the following commands:
sudo tee /etc/resolver/docker.localhost \>/dev/null \<\<EOF nameserver 127.0.0.1 EOF
is the top-level domain name that I've configured Dnsmasq to respond to and127.0.0.1 is the IP address of the server to use.
Once you’ve created this file, OS X will automatically read it and you’re done!
Testing you new configuration is easy; just use
ping check that you can now resolve some DNS names in your new top-level domain:
# Make sure you haven't broken your DNS. ping -c 1 www.google.com # Check that .dev names work ping -c 1 this.is.a.test.docker.localhost ping -c 1 iam.the.walrus.docker.localhost
You should see results that mention the IP address in your Dnsmasq configuration like this:
PING iam.the.walrus.docker.localhost (127.0.0.1): 56 data bytes
You can now just make up new DNS names under.docker.localhost whenever you please. Congratulations!