Make Traefik Load-balance Docker and External Services
I spent some time trying to figure it out, but eventually cracked the problem. Below is an logical diagram of what I wanted.
Spoiler alert: You cannot do everything with Docker labels
I really like Traefik's way on configuring services with docker labels. I tried a number of different ways using labels to define services external to Docker and ask Traefik to route there.
No luck.
In the end the only way I was able to make it work was to add the definition to an external file, at which point everything worked smoothly.
Show me the config!
Right, so I guess you want to see some config code. This is my traefik_conf.yml which is mounted into the Traefik container.
In this particular case we are proxying a URI off my main domain to a new service. In this case, https://www.simplecto.com/mynewservice will be proxied to an externally hosted service on http://10.10.100.200:8080.
It also uses the stripprefix middleware.
I prefer this case because it minimizes the number of subdomains to manage in DNS.
traefik_conf.yml
http:
routers:
mynewservice:
service: mynewservice
middlewares:
- "mynewservice-stripprefix@file"
rule: "Host(`www.simplecto.com`) && PathPrefix(`/mynewservice`)"
tls:
certResolver: le
services:
mynewservice:
loadBalancer:
servers:
- url: "http://10.10.100.200:8080"
middlewares:
mynewservice-stripprefix:
stripPrefix:
prefixes:
- "/mynewservice"
this is a part of my docker-compose.yml that configures traefik with command line options.
version: '3'
services:
traefik:
container_name: traefik
image: traefik:v2.1
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--entryPoints.web.address=:80"
- "--entryPoints.websecure.address=:443"
- "--certificatesResolvers.le.acme.email=email@domain.com"
- "--certificatesResolvers.le.acme.storage=acme.json"
- "--certificatesResolvers.le.acme.tlsChallenge=true"
- "--certificatesResolvers.le.acme.httpChallenge=true"
- "--certificatesResolvers.le.acme.httpChallenge.entryPoint=web"
- "--providers.file.filename=/traefik_conf.yaml"
- "--accesslog=true"
- "--accesslog.filepath=/logs/access.log"
- "--accesslog.bufferingsize=100"
restart: always
ports:
- 80:80
- 443:443
- 8080:8080
networks:
- traefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/acme.json
- ./traefik_conf.yaml:/traefik_conf.yaml:ro
- ./logs:/logs
labels:
Pay particular attention to this line.
- "--providers.file.filename=/traefik_conf.yaml"
This tells docker to pull file configs.
Also, notice in the volumes:
section where we bind-mount the config file to the container.
Conclusion
Honestly, this was more for me than it was for you. I put up many of these posts just so that I don't forget. Hopefullly it helps you as well.
Feel free to email me or reach out for any comments / suggestions to improve this arrangement.