This is a rundown of how my local web development environment on macOS uses Traefik as a reverse proxy to route traffic to Docker containers over HTTPS. I created this for my own reference since I am not an expert, but hopefully it can help someone else and maybe find some suggested improvements.
Note: This guide was originally created using an Intel Mac, but some changes and additions were made after switching to Apple silicon. Exact file paths or steps may very between platforms.
- Reverse proxy for local Docker containers
- Fixes browser certificate warnings
- Automatically redirects http traffic to https
We will be using Dnsmasq to make sure all domains using the .test TLD are pointed at our local machine and Traefik can handle the requests. We could use 127.0.0.1 as our target and everything will work fine on our host, but when we try to resolve a .test domain from inside a container 127.0.0.1 will refer to the current container. To solve this we can create a loopback interface and use that IP.
- Install Dnsmasq using
brew install dnsmasqon the host machine. - Start the service using
sudo brew services start dnsmasq - Open the config file at
/opt/homebrew/etc/dnsmasq.confand uncomment the line#conf-dir=/opt/homebrew/etc/dnsmasq.d/,*.confnear the end of the file. - Next we will configure Dnsmasq to point all domains using our
.testTLD to10.254.254.254. To do this create a file at/opt/homebrew/etc/dnsmasq.d/development.confwith the contentsaddress=/.test/10.254.254.254 - Run
sudo ifconfig lo0 alias 10.254.254.254to create an IP address alias (note: this will not persist across a reboot, so here is a potential solution) - Restart dnsmasq using
sudo brew services restart dnsmasq - Confirm everything works so far by running
dig foobar.test @127.0.0.1 +short. The output should match the alias we created. - Now we need to add a resolver. Create a directory using
sudo mkdir /etc/resolverthat will contain our resolver. Then create a file namedtest(the name corresponds to our.testTLD) with the contentsnameserver 127.0.0.1 - Confirm everything is set up using
ping -c 1 foobar.test
- Create a Docker network named "web" by running
docker network create web - After you've configured your projects and set up your
dynamic_conf.ymlwith the appropriate certs, rundocker-compose up -dto start Traefik - The Traefik dashboard should now be visible at http://localhost:8080
For a container to be accessible to Traefik, we will be adding it to the "web" Docker network we created. We should also assign it to the "default" network if we want to connect to other containers (like a database) in the same project.
We will also need to add labels so that Traefik knows how to route traffic. Use the name of the project as our router name.
These can be added directly to our docker-compose.yml file or to a docker-compose.override.yml file if preferred.
services:
webserver:
networks:
- default
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`projectdomain.test`)"
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
- "traefik.docker.network=web"
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=80"
networks:
web:
external: true- Ensure mkcert is installed by running
brew install mkcertas well asbrew install nssif you use Firefox - Create local CA by running
mkcert -install - Change into
certsdirectory - Run
mkcert mydomain.testormkcert "*.mydomain.testfor a wildcard - Create
dynamic_conf.ymlby switching back to the root directory and runningcp dynamic_conf.example.yml dynamic_conf.ymland then making the necessary changes
# Dynamic configuration
tls:
certificates:
- certFile: "/etc/traefik/certs/mydomain.test.pem"
keyFile: "/etc/traefik/certs/mydomain.test-key.pem"
- certFile: "/etc/traefik/certs/_wildcard.mydomain.test.pem"
keyFile: "/etc/traefik/certs/_wildcard.mydomain.test-key.pem"Because our CA is on our host machine, we'll need to add it to any containers that connect to another via a secure URL using one of our generated certificates. The exact Dockerfile changes needed may vary based on the image, but this example seems to work on Ubuntu.
- Run
mkcert -CAROOTin terminal to find the location of our CA - Copy
rootCA.pemfrom this location into our build directory - Add the following to our Dockerfile to install the CA into the image
COPY rootCA.pem /usr/local/share/ca-certificates/rootCA.crt
RUN chmod 644 /usr/local/share/ca-certificates/rootCA.crt && update-ca-certificates;Thanks to the authors of these articles that helped me scrape this together.