Within this guide I will guide you step by step throu a setup of a local DNS setup to resolve local services as well as services running within Docker. Within this guide I will use Homebrew to install the required services, please follow the official instructions to install it.
We will use .lan
as toplevel domain for local name resolution, all our
services will be available by this name. To get it working on nearly all
environments I will also attach a private IP to our loopback network interface
where I have choosen 10.254.254.254
, this is required to get the host and the
Docker services resolving the same names.
First I will make sure that our private IP gets assigned to our loopback interface, with this service it will also be set up again after rebooting the host. You can define as many aliases as you want, but for this guide a single IP should be totally fine.
cat << EOF | sudo tee /Library/LaunchDaemons/de.webhippie.loopback1.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>de.webhippie.loopback1</string>
<key>ProgramArguments</key>
<array>
<string>/sbin/ifconfig</string>
<string>lo0</string>
<string>alias</string>
<string>10.254.254.254</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
EOF
To keep the IP alias persistant accros reboots I need to load this defined
.plist
file via launchctl
, otherwise the IP is lost after a reboot.
sudo launchctl load /Library/LaunchDaemons/de.webhippie.loopback1.plist
You can check if the service is loaded properly by checking it with launchctl
:
sudo launchctl list | grep de.webhippie
For the local name resolution I will install dnsmasq which is a simple local nameserver, it also provides more features, but I won't need them for our setup.
brew install dnsmasq
Next I need to add our local domain to the dnsmasq configuration file. You can simply echo the required changes into the configuration files.
echo "conf-dir=/usr/local/etc/dnsmasq.d/,*.conf" | tee -a /usr/local/etc/dnsmasq.conf
echo "address=/lan/10.254.254.254" | tee /usr/local/etc/dnsmasq.d/lan.conf
To finally start the service you can simply launch it with Homebrew, this will wrap the macOS service start scripts and will also start the service in the background after a reboot.
sudo brew services start dnsmasq
You can quite simple confirm that the name resolution works as expected just by
executing dig @127.0.0.1 foo.lan
, this should result in a response like:
; <<>> DiG 9.10.6 <<>> @127.0.0.1 foo.lan
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4845
;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;foo.lan. IN A
;; ANSWER SECTION:
foo.lan. 0 IN A 10.254.254.254
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Sep 13 09:47:08 CEST 2019
;; MSG SIZE rcvd: 52
To automatically resolve all .lan
domains to our previously installed
dnsmasq I also got to define a local resolver, just execute the
following command to properly resolve local names.
echo "nameserver 127.0.0.1" | sudo tee -a /etc/resolver/lan
You can confirm that the resolver is configured properly by simply executing
scutil --dns
, this should show the newly defined .lan
resolver similar to
this:
resolver #8
domain : lan
nameserver[0] : 127.0.0.1
flags : Request A records
reach : 0x00000002 (Reachable)
To get Docker fo Mac installed you can simply install it via
Homebrew, just execute the following command to get it. After the
successfull installation you got to initially start it once, press ⌘ + Space
and enter docker
, press Enter
.
brew cask install docker
To confirm that Docker is working as expected you can execute docker info
to
see if it prints some version information.
As usual there are quite often the scenarios where you want to run your local services with SSL, for that case I am using mkcert, which generates certificates for you and adds them automatically to your browser. But first I need to install it.
brew install mkcert nss
After installing the required packages you got to generate and install the custom root certificate by executing:
mkcert -install
Finally I will generate our wildcard certificate for our defined .lan
toplevel domain. You can store it whereever you like, I will just put it into my
local ownCloud folder:
mkdir -p ~/ownCloud/Documents/Certificates
cd ~/ownCloud/Documents/Certificates
mkcert \*.lan
You should have two files generated now, they are named _wildcard.lan-key.pem
and _wildcard.lan.pem
.
To have a proper reverse proxy for our Docker services I am using Traefik which is a great piece of software.
docker run -d \
--restart always \
--name traefik \
--publish :80:80 \
--publish 443:443 \
--volume ${HOME}/ownCloud/Documents/Certificates:/etc/certs \
--volume /var/run/docker.sock:/var/run/docker.sock \
--label traefik.port=8000 \
traefik:1.7 \
--traefiklog \
--accesslog \
--api \
--docker \
--docker.domain=lan \
--defaultentrypoints=http \
--defaultentrypoints=https \
--entrypoints='Name:traefik Address::8000' \
--entrypoints='Name:http Address::80' \
--entrypoints='Name:https Address::443 TLS:/etc/certs/_wildcard.lan.pem,/etc/certs/_wildcard.lan-key.pem'
To confirm that caddy is working as expected you can simply use curl or your browser and access http://traefik.lan, this should show the traefik dashboard.