Traefik is being used to act as a load-balancer and proxy for the various micro and data services. Traefik requires access to your Docker Host. On a local dev box this means sharing the
/var/run/docker.sock file with the container, but on remote hosts, exposing the remote docker host port either insecure in a highly trusted environment (port 2375), or over SSL (2376).
The build process will automatically use the local docker socket file unless otherwise configured.
To fully use the service discovery feature, a local DNS service has been added. This allows for local host resolution of the *.example.dev domain name.
Note: it is suggested to move the base data services into a separate project so that they can be shared with other micro services.
- http://dns.example.dev/ - DNSMasq console
- http://proxy.example.dev/ - Traefik Console / Monitoring
- http://rabbit.example.dev/ - RabbitMQ Management Panel
Setup Local DNS Resolution
These instructions are for macOS. For other operating systems, Google it or set custom DNS servers to use your localhost port 1034.
Create a new resolver configuration file:
sudo mkdir /etc/resolver cd /etc/resolver sudo nano -w example.dev
Add the following contents to this file:
domain example.dev nameserver 127.0.0.1 port 1034 search_order 10
Save the changes (Ctrl+O) (oh, not zero) and exit (Ctrl+X).
Check your DNS via
sudo scutil --dns it should have output similar to:
resolver #8 domain : example.dev nameserver : 127.0.0.1 port : 1034 flags : Request A records, Request AAAA records reach : 0x00030002 (Reachable,Local Address,Directly Reachable Address) order : 10 DNS configuration (for scoped queries) resolver #1 nameserver : 188.8.131.52 nameserver : 184.108.40.206 if_index : 8 (en0) flags : Scoped, Request A records reach : 0x00000002 (Reachable)
Finally: make sure any local
/etc/hosts entries are removed otherwise they will interfere with the DNS resolution. Either comment them out or delete the lines entirely.
/etc/resolver only reloads on file changes, not file edits. If you make a mistake and need to reload the file,
sudo touch tmp and then
sudo rm tmp to force a reload.
Note: you may need to clear your dns cache as well:
sudo killall -HUP mDNSResponder
Automatic Service Discovery
Traefik acts as a proxy and load balancer in a similar way to nginx. It listens on port 80 (or any other) and provides a gui (usually on 8080, but proxy.example.dev:80 gives access as well). LetsEncrypt can be setup to provide SSL as well as HTTP auth etc.
To register containers with Traefik (called
proxy in this project), you need to label the container with specific tags. Any web service should be labeled with:
- traefik.http.* with configuration directives
By default, Traefik will not register new services - they must be explicitly configured.
For example: to expose the example App API and have Traefik route it:
services: app: build: context: . dockerfile: src/Resources/docker/dev/app/Dockerfile networks: - backend labels: traefik.enable: true traefik.http.routers.app.rule: "Host(`app.example.dev`)" traefik.http.routers.app.tls: true traefik.http.services.app.loadbalancer.server.port: 8080
By default, the proxy service has automatic SSL forwarding on all hosts, however each app still needs to explicitly set this. If you are using a
.dev domain name, then these must be served over SSL.
Each of the
http config options needs setting to the services name that this config applies to. In this example, the service name is "app" - that is the key under the services. This is then used in each of the router and services options. If your service is named "webserver" then these labels would be written as:
services: webserver: labels: traefik.enable: true traefik.http.routers.webserver.rule: "Host(`app.example.dev`)" traefik.http.routers.webserver.tls: true traefik.http.services.webserver.loadbalancer.server.port: 8080
server.port is the INTERNAL container port that Traefik should forward requests to. Typically this is whatever is exposed in the containers Dockerfile e.g.: 8080, 9000, 5432, etc etc. If there is only one port exposed, this option can be left of, however if there is more than one it must be provided.
All that is left to do is
dc up -d and Traefik will pick up the new container and it will be made available via whatever hostname was set (presuming you are also using the DNS resolver).
dc down services will automatically be removed.
As the Traefik config is done through labels, they can be added safely to docker-compose files without interfering with any other configuration.
Note: you should ensure that any services use the same named network that Traefik is running under to avoid issues with routing. By default the network name is:
mycompany_network_backend. You should change this to reflect your projects name; then in services that need registering ensure that an external network is defined:
networks: mycompany_network_backend: external: true