Local domain names and routing for Docker on Mac does not work
ottok opened this issue · 7 comments
On Linux (e.g. Ubuntu 18.04) a simple docker-composer command is enough to get a fully equivalent developer experience as with vagrant up
. The Docker container uses a bridged network, becomes visible with its own IP address to the Linux host, and advertises its local domain names with Avahi/mDNS. For example the IP and port here Nginx of the container would be listening could be 192.168.208.2:80. Users can simply open https://wordpress.local
in their browser and start working.
On Mac however, the network: bridge
stanza in the docker-compose.yml
is not honored and it does not get its own IP address. Instead, the running container is only visible by the random port numbers assigned by Docker on the Docker host IP, for example 127.0.0.1:32774. The problem is twofold: no DNS is advertised, and even if it was, there is no real IP with a website served at port 80.
The available solutions seems to be running a proxy container at 127.0.0.1:80 (and :443) that then directs all traffic to the actual containers inside the Docker network. Often https://github.com/jwilder/nginx-proxy seems to be used, together with https://github.com/jwilder/docker-gen to populate the proxy config. In addition you need something injected to the local DNS, and some people seem to use https://github.com/andyshinn/dnsmasq to highjack one TLD to be served from a local DNS server (for example *.test).
Considering there are also other challenges with Docker on Mac (e.g. slow data volume mounts, for which people seem to use e.g. http://docker-sync.io/ to speed them up) it seems that using Docker on Mac does not make much sense, and running the regular Vagrant box with all to tried and tested automation around networks, DNS and data mounts that Vagrant already has is a much cleaner solution with no known major drawbacks.
This issue should be kept open until somebody figures out how to run true bridged container networks on Docker for Mac (or if upstream introduces such features).
TODO:
- Test all network options on Mac: https://docs.docker.com/network/
- Check if any of this applies on Mac: https://docs.docker.com/network/bridge/
- Find out if there are more docs for Docker for Mac networking than https://docs.docker.com/docker-for-mac/#network
Let me know if you need help with this.
From https://docs.docker.com/docker-for-mac/networking/
There is no docker0 bridge on macOS
Because of the way networking is implemented in Docker Desktop for Mac, you cannot see a docker0 interface on the host. This interface is actually within the virtual machine.I cannot ping my containers
Docker Desktop for Mac can’t route traffic to containers.Per-container IP addressing is not possible
The docker (Linux) bridge network is not reachable from the macOS host.
We're running a bunch of local Drupal development environments on Docker and wanted to keep the Docker workflow with WP. Our local Drupal setup is based on Wodby's Docker4Drupal (https://github.com/Wodby/docker4drupal) and therefore we already had a robust container routing solution built on Træfik (https://docs.traefik.io/). Routing requests to the correct container is quite easy using Træfik:
- Add the external Træfik network to the container
- Add a label to the container that sets the Træfik routing rule
The .local
TLD is reserved by macOS to be used to discover Bonjour/Rendezvous/Zeroconf services advertised using mDNS. It would make it a bit easier on macOS users if the .local
TLD was swapped to some other TLD (we've been using .localhost
). Using .local
is feasible, though. You just need to make sure you have:
- A local DNS (like dnsmasq) configured to resolve
.local
domains - A resolver entry added to
/etc/resolver/local
that forces.local
domains to use the local DNS - Network configuration set to use a DNS to resolve
.local
domains
That third part is something that is specific to using .local
domains on macOS. By default .local
domains are not resolved using DNS. Making this configuration change breaks the Bonjour functionality on macOS that relies on mDNS.
Anyway, I got the thing working on macOS with a bit of tinkering. It's not overly complicated but it does need Træfik, dnsmasq and macOS network settings properly configured.
Also, the data volume mounts can be set to use user guided caching on macOS which makes them a lot faster. We've had stellar performance gains on our Drupal environments with them and they basically just work.
If you guys want some help with this we're happy to help!
Some people seem to run Traefik on localhost:80 and use it to route traffic to other containers. These setups don't have any DNS, they just use example.docker.localhost or example.host.internal, which is provided by default by Docker as a catch-all address to point to localhost IP.
Did some experiements with Traefik. Results:
Vagrant | Docker with Traefik | Plain Docker | |
---|---|---|---|
Start command | vagrant up | docker-compose up | docker-compose up |
Site name | Inherited from config.yml | Inherited from .env or from run-time env SITE | Inherited from .env or from run-time env SITE |
Domain names | Vagrant plugin manages /etc/hosts, each domain points to the virtual machine IP | All domains subdomains of *.localhost, all point to 127.0.0.1 where Traefik then occupies port 80, 443 and 22 | Avahi announces DNS names on the network automatically, each domain points to the Docker container IP |
SSH into dev | vagrant ssh | Does not work, port 22 on Traefik cannot route SSH by domain as SSH does not have any SNI headers | ssh wordpress.local -F .vagrant/ssh/config |
SSH from dev to prod | vagrant ssh; wp-pull-production-db works flawlessly | Since SSH does not work,need to use ‘docker exec’ to access container. Inconveniently long command and SSH agent does not work, thus wp-pull-production-db always asks for password. | ssh wordpress.local -F .vagrant/ssh/config; wp-pull-production-db works flawlessly |
I tested feature/traefik
branch but it got stuck on generating certificate:
traefik | time="2020-11-30T21:37:10Z" level=debug msg="No default certificate, generating one"