Make Traefik Load-balance Docker and External Services

A quick cheat sheet and example configuration that configures Traefik to loadbalance across docker networks and external networks.

I spent some time trying to figure it out, but eventually cracked the problem. Below is an logical diagram of what I wanted.

Logical layout of what I want to do

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.

Subscribe to Candid and colorful thoughts on enterprise readiness

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe