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.