Seravo / wordpress

The WordPress project layout used by many of Seravo's customers, suitable also for local development with Vagrant and git deployment
https://seravo.com
GNU General Public License v3.0
102 stars 54 forks source link

Local domain names and routing for Docker on Mac does not work #126

Open ottok opened 4 years ago

ottok commented 4 years ago

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).

ottok commented 4 years ago

TODO:

tlxo commented 4 years ago

Let me know if you need help with this.

ottok commented 4 years ago

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.

Kimitri commented 4 years ago

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:

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:

  1. A local DNS (like dnsmasq) configured to resolve .local domains
  2. A resolver entry added to /etc/resolver/local that forces .local domains to use the local DNS
  3. 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!

ottok commented 3 years ago

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.

ottok commented 3 years ago

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
samikeijonen commented 3 years ago

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"