Getting Local Domains to Work with Kubernetes in Docker Desktop for Mac
In this guide, I will show you how to set up local DNS to work with Kubernetes in Docker Desktop for Mac. We’re going to send
*.localhost domain traffic to your local Kubernetes cluster with the help of
dnsmasq and some clever IP routing.
Configuring the Host Mac
Make a Loopback Alias
126.96.36.199 into a loopback alias that points at your Mac.
sudo ifconfig lo0 alias 188.8.131.52
You can turn this into a
plist so that the configuration survives reboots. Make a file
/Library/LaunchDaemons/localhost.docker.kubernetes.loopback.plist containing the following:
<?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>localhost.docker.kubernetes.loopback.plist</string> <key>ProgramArguments</key> <array> <string>ifconfig</string> <string>lo0</string> <string>alias</string> <string>184.108.40.206</string> </array> <key>RunAtLoad</key> <true/> </dict> </plist>
Install it via Brew.
brew install dnsmasq
Append the following line to
dnsmasq.conf, which will tell
dnsmasq to load additional
*.conf configuration files from the
Create a new file
/usr/local/etc/dnsmasq.d/localhost.conf that directs
*.localhost domains to
220.127.116.11 like this:
Restart the service.
sudo brew services restart dnsmasq
Make a new file
/etc/resolver/localhost to tell your Mac to use its
dnsmasq service to resolve
Configuring the Virtual Machine (VM)
iptables to tell the VM to forward
192.168.65.2 (its address for your Mac). The following command uses a minimal Docker image with
nsenter(1) to punch through to the containing VM and run
docker run -it --privileged --pid=host justincormack/nsenter1 /bin/bash -c "iptables -t nat -A OUTPUT -d 18.104.22.168 -j DNAT --to-destination 192.168.65.2"
How Does it Work?
- The VM sends
22.214.171.124traffic to your Mac.
- Your Mac sends
126.96.36.199traffic to itself.
- Both use
dnsmasqalways answers with
*.localhostdomains, resolved from either your Mac or the VM, always indicate an IP address that routes traffic back to your Mac.
What’s the Deal With the IP Address?
A typical guide for using
dnsmasq for local development would tell you to set
*.localhost to resolve to
127.0.0.1. That works for your Mac.
The problem with doing that is when your VM resolves
127.0.0.1. On your VM,
127.0.0.1 is the VM itself. We don’t want
foo.localhost to go to the VM. We want it to go to the host Mac and let the host Mac handle the routing from there.
So we have
foo.localhost resolve to
188.8.131.52, an arbitrary IP address from the private network block. And we separately configure both the host Mac and the VM to loop that traffic back to the host Mac.
Testing It Out
kubectl is pointed at the
kubectl config use-context docker-desktop
Install the nginx ingress controller like so:
kubectl apply --wait -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.27.1/deploy/static/mandatory.yaml kubectl apply --wait -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.27.1/deploy/static/provider/cloud-generic.yaml
http://anything.localhost in your browser. If everything is working properly, you will see a generic 404 Not Found page.
Did it work for you? Let us know on Twitter!
From 0 to K8s in Hours, Not Months
You might also be interested in these articles: