Home > traefik-reverse-proxy

January 20, 2026


My docker containers are served by Traefik reverse proxy

A reverse proxy is a single place where all traffic enters your network. This has a lot of benefits in a Docker environment:

  • You can configure a custom domain name for every container application and have the reverse proxy handle the routing
  • You can setup a single SSL/TLS certificate that secures traffic for all your application over HTTPS, and redirect all unsecure HTTP to HTTPS
  • You can even add an authentication layer to applications so they can only be accessed with a username and password, something i have not touched yet
  • More…

Setting up Traefik

Preparations

Make sure you have docker and docker compose installed.

I decided to use local self-signed SSL certificates because the encryption is purely for the traffic in my LAN. I have a blog post that explains how to generate these certificates and make your browser trust them on Windows and Iphone. If you want to use a certificate authority like Let’s Encrypt, the Traefik docs has this documented well.

Deploying

Create a network for your Traefik container and the containers to be routed by the reverse proxy, so they can communicate with each other:

docker network create proxy

Let’s create a config file for traefik. I put mine in the /config folder and named it traefik.yaml:

global:
  checkNewVersion: false
  sendAnonymousUsage: false
log:
  level: INFO
accesslog: true
api:
  dashboard: true
  insecure: false
entryPoints:
  web:
    address: :80
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true
  websecure:
    address: :443
providers:
  docker:
    exposedByDefault: false
    network: proxy
  file:
    directory: /dynamic
    watch: true

Brief explanation for the most important configurations:

  • The api has its entry dashboard set to true to deploy the UI dashboard for Traefik. The insecure entry is set to false to server it with secure HTTPS
  • In entryPoints we have the web entry that configures port 80 to be redirected to the websecure scheme, which is bound to port 443. In other words, HTTP is redirected to HTTPS.
  • The providers entry specifies a docker provider with network proxy, which we created earlier. It also has exposedByDefault set to false. This means Traefik does not route traffic for a container by default, we have to explicitly configure this.
  • The file provider is configured to watch the folder with the dynamic configuration, where my certificates are stored. We will configure this next.

In the /dynamic folder, create tls.yaml. This file defines the paths to the self-signed certificates inside the container:

tls:
  certificates:
    - certFile: /certs/wildcard.server.home.crt
      keyFile: /certs/wildcard.server.home.key

To put it all together, we create the compose.yaml :

services:
  traefik:
    container_name: traefik
    image: traefik:v3.6
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro # Docker socket
      - ./config/traefik.yaml:/etc/traefik/traefik.yaml:ro
      - ./dynamic:/dynamic:ro
      - ./config/certs:/certs:ro
    networks:
      - proxy
    restart: unless-stopped
    labels:
      - "traefik.enable=true"

      # Dashboard router
      - "traefik.http.routers.dashboard.rule=Host(`$TRAEFIK_DASHBOARD_DOMAIN`)"
      - "traefik.http.routers.dashboard.entrypoints=websecure"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.tls=true"

      # Basic‑auth middleware
      - "traefik.http.middlewares.dashboard-auth.basicauth.users=$USER:$PASSWORDHASH"
      - "traefik.http.routers.dashboard.middlewares=dashboard-auth@docker"

networks:
  proxy:
    external: true

We expose ports 80 and 443 for Traefik to accept al HTTP and HTTPS traffic, after which tt can route the traffic to the corresponding container. Port 8080 is exposed for dashboard access.
We mount the Docker socket to a location inside the container so Traefik can dynamically configure other containers according to docker labels. Also mounted are the aforementioned Traefik.yaml file and /dynamic directory. The location of your SSL certificates need to be mounted to /certs.
We use the proxy network that we created earlier. All the new containers that you want to put behind the reverse proxy also need to use this network.

Finally, the Traefik labels are defined. Replace $TRAEFIK_DASHBOARD_DOMAIN with the domain you want for the dashboard. If you prefer your dashboard to be secured with a username and password, you can generate the $USER:$PASSWORDHASH string with the following command, using your preferred credentials:

htpasswd -nb admin password

If you dont need authentication you can remove the two labels for the basic-auth middleware.

Deploy the container by executing the following command in the directory with the compose.yaml:

docker compose up -d

That’s it! Your dashboard should be accessible with your custom domain. Enjoy 🚀🚀🚀

A Final Remark

Final words for the mega struggle i had to make Traefik work in my setup. Watched and read so many how-to tutorials but couldn’t get it to work. I got 404 not found errors for every domain i tried to setup with Traefik.

Turned out i forgot about the K3s cluster that i had started on my server to practice Kubernetes for the CKAD certification i passed (😎) a month ago. The cluster occupied port 80 while my Linux machine and Traefik were both convinced that the port was open. Actually also tried Nginx reverse proxy and Caddy while desperately looking for something that worked, but Traefik got lucky to be the one i worked on while stumbling upon the cause of the problem.