Traefik and single-host Docker

Before diving in, let’s first establish my use case, which is likely very similar to yours.

I have Docker deployed to my virtualization server with plenty of containers running on it – Portainer, Frigate NVR, Bitwarden, etc. – plus a couple VMs. And I started using Traefik after discovering it with my current employer’s Kubernetes clusters.

For the uninitiated, Traefik Proxy, specifically, allows you to use hostnames to route traffic to your containers rather than relying on port numbers. Then you just need to make sure you have proper DNS resolution for the new hostname. Traefik then uses routing rules to determine which container gets the traffic, keying off the hostname provided via SNI or the Host header in an HTTP request.

And it’s a far less complicated means of putting your browser-accessible containers and services behind an HTTPS proxy.

Almost all of the containers deployed to my Docker server are isolated to their own networks and spun up or down using docker compose. Only two of those Docker services are not behind Traefik: Plex and a MySQL container I use for GnuCash. The MySQL client supports SNI as of version 8.1.0. GnuCash relies on DBD::MySQL, which does not support SNI as of this writing. Plex requires host networking when deployed as a Docker container.

And so does Traefik if you want it to route traffic seamlessly.

Traefik also makes a binary distribution you can run as a service outside Docker. And it might be available from your distro’s package manager. But beware that it may not be the latest version, so you might be missing out on critical security updates like the CVE fix in v3.6.7, the latest version as of this writing.

It’s safe to say, though, that the vast majority of Traefik deployments are via docker compose or the Helm chart for Kubernetes clusters. And as mentioned, I have Traefik deployed via Docker, which is where this comes in:

services:
  traefik:
    image: traefik:v3.6
    container_name: traefik
    restart: unless-stopped

    network_mode: host

    volumes:
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock
        read_only: true

      - type: bind
        source: ./certs
        target: /certs
        read_only: true

      - type: bind
        source: ./dynamic
        target: /dynamic
        read_only: true

      - type: bind
        source: ./traefik.yml
        target: /etc/traefik/traefik.yml

    labels:

      - traefik.enable=true
      - traefik.docker.network=traefik

      # When using host networking, you can't use the "api@internal" service.
      # to access the dashboard. Instead you need to You have to link the
      # dashboard (port 8080) to a new one.

      - traefik.http.services.traefik.loadbalancer.server.port=8080
      - traefik.http.routers.traefik.service=traefik

      - traefik.http.routers.traefik.entrypoints=websecure
      - traefik.http.routers.traefik.rule=Host(`traefik`) || Host(`traefik.localdomain`)

And alongside the docker-compose.yaml is this traefik.yaml for configuration.

global:
  checkNewVersion: true
  sendAnonymousUsage: false

log:
    level: INFO

accessLog: true

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true

  websecure:
    address: ":443"
    http:
      tls: true

  # Add any other ports you need - e.g., 3306 for MySQL, 6379 for Redis, etc.

providers:
  docker:
    exposedbydefault: false

  file:
    filename: /dynamic/tls.yaml

api:
  dashboard: true
  insecure: true

And this is the folder structure where these files live:

traefik/
|- certs/
|- [container1.crt]
|- [container1.key]
|- [container2.crt]
|- [container2.key]
|- ...
|- dynamic/
|- tls.yaml
|- docker-compose.yml
|- traefik.yml

So the above should be enough to get you started using Traefik with Docker. Change settings where you need – e.g., dumping logs to files instead of the output available via docker logs.

You will need to read the documentation for deploying your individual services with the proper labels so they are properly picked up by Traefik.