1. Blog
  2. Manuals

Traefik 3: Installation, Configuration and Docker Examples

Traefik 3: Installation, Configuration and Docker Examples

Traefik is a reverse proxy built for containers. It discovers running Docker services on its own, reads routing rules from their labels and issues SSL certificates automatically. To publish a new service you do not edit the proxy configuration — you add a few lines to that service’s docker-compose.yml.

Core concepts

  • Entrypoint — a port where Traefik accepts requests: usually 80 and 443.
  • Router — a rule that sends a request to a service, for example by domain name.
  • Service — the container that handles the request.
  • Middleware — processing in between: authentication, redirects, headers, rate limiting.
  • Certificate resolver — how SSL certificates are obtained.

What you need

  • a VPS with Docker and Docker Compose — see the installation guide;
  • domains with A records pointing to the server;
  • ports 80 and 443 free.

Step 1. Install Traefik

mkdir -p ~/traefik && cd ~/traefik

Create docker-compose.yml:

services:
  traefik:
    image: traefik:v3
    container_name: traefik
    restart: unless-stopped
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=proxy
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.le.acme.email=admin@example.com
      - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.le.acme.tlschallenge=true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
    networks:
      - proxy

networks:
  proxy:
    name: proxy

What this configures:

  • exposedbydefault=false — Traefik publishes only containers that explicitly allow it with a label;
  • all traffic on port 80 is redirected to HTTPS;
  • Let’s Encrypt certificates are issued automatically and stored in the letsencrypt directory;
  • the shared proxy network connects Traefik to the other containers.

Start it:

docker compose up -d

Step 2. Publish your first service

In a separate directory, create a docker-compose.yml for a test service:

services:
  whoami:
    image: traefik/whoami
    restart: unless-stopped
    networks:
      - proxy
    labels:
      - traefik.enable=true
      - traefik.http.routers.whoami.rule=Host(`whoami.example.com`)
      - traefik.http.routers.whoami.entrypoints=websecure
      - traefik.http.routers.whoami.tls.certresolver=le

networks:
  proxy:
    external: true
docker compose up -d

Within a few seconds the service opens at https://whoami.example.com with a valid certificate. You do not publish the container’s ports: Traefik reaches it over the internal network.

If a container listens on several ports, or the image does not declare one, set it explicitly:

      - traefik.http.services.whoami.loadbalancer.server.port=80

Step 3. Dashboard

The built-in dashboard shows every route, service and configuration error. It must not be exposed without a password.

Create a password hash:

sudo apt install -y apache2-utils
htpasswd -nB admin

Add this line to the Traefik container’s command:

      - --api.dashboard=true

and these labels to the same service, doubling every $ sign in the hash:

    labels:
      - traefik.enable=true
      - traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)
      - traefik.http.routers.dashboard.entrypoints=websecure
      - traefik.http.routers.dashboard.tls.certresolver=le
      - traefik.http.routers.dashboard.service=api@internal
      - traefik.http.routers.dashboard.middlewares=dashboard-auth
      - traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$2y$$05$$...

After docker compose up -d the dashboard is available at https://traefik.example.com.

Useful middleware

Middleware is declared with a label and attached to a router by name. Several middlewares are listed separated by commas.

Security headers:

      - traefik.http.middlewares.secure.headers.stsSeconds=31536000
      - traefik.http.middlewares.secure.headers.contentTypeNosniff=true
      - traefik.http.middlewares.secure.headers.frameDeny=true
      - traefik.http.routers.whoami.middlewares=secure

Rate limiting:

      - traefik.http.middlewares.limit.ratelimit.average=50
      - traefik.http.middlewares.limit.ratelimit.burst=100

Access from specific addresses only:

      - traefik.http.middlewares.office.ipallowlist.sourcerange=198.51.100.0/24

Redirect from www to the apex domain:

      - traefik.http.routers.site-www.rule=Host(`www.example.com`)
      - traefik.http.routers.site-www.middlewares=to-apex
      - traefik.http.middlewares.to-apex.redirectregex.regex=^https://www\.(.*)
      - traefik.http.middlewares.to-apex.redirectregex.replacement=https://$${1}
      - traefik.http.middlewares.to-apex.redirectregex.permanent=true

Wildcard certificate

A certificate for all subdomains is issued through DNS validation. Replace the tlschallenge line with your DNS provider’s settings, for example Cloudflare:

      - --certificatesresolvers.le.acme.dnschallenge=true
      - --certificatesresolvers.le.acme.dnschallenge.provider=cloudflare

and pass the API token in the CF_DNS_API_TOKEN environment variable. List the certificate’s domains on the router:

      - traefik.http.routers.app.tls.domains[0].main=example.com
      - traefik.http.routers.app.tls.domains[0].sans=*.example.com

Migrating from Traefik 2

A version 2 configuration is mostly compatible with version 3. What to check:

  • Rule syntax. HostRegexp and PathPrefix no longer accept named patterns like {name:regex} — plain regular expressions are used. During the transition you can keep the old syntax with --core.defaultRuleSyntax=v2.
  • Docker Swarm. Swarm mode moved out of the Docker provider into a separate swarm provider.
  • The ipWhiteList middleware was renamed to ipAllowList.

Read the official migration guide before upgrading and test the configuration on a staging server.

Troubleshooting

docker logs traefik
  • 404 page not found — Traefik found no route: check the traefik.enable=true label, the Host rule and the shared network.
  • No certificate is issued — the domain does not point to the server, or port 443 is closed. Let’s Encrypt limits the number of attempts, so enable the staging server while debugging: --certificatesresolvers.le.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory.
  • Gateway Timeout — the container is not attached to the proxy network, or the service port is wrong.
  • Verbose log — add --log.level=DEBUG.

Traefik or manual Nginx

Traefik shines when there are many services and they change often: all configuration lives next to the service and is kept in Git. If you have a handful of static sites and want full control, plain Nginx virtual hosts are simpler. If you prefer configuring a proxy in a web interface, choose Nginx Proxy Manager.