Traefik Docker Guide 2026: The Ultimate Reverse Proxy
TUTORIAL 11 min read fordnox

Traefik Docker Guide 2026: The Ultimate Reverse Proxy

Set up Traefik with Docker for automatic SSL, service discovery, and load balancing. Complete guide for modern container deployments.


Traefik Docker Guide: Automatic Reverse Proxy

Traefik is the cloud-native reverse proxy. It discovers your Docker containers and automatically routes traffic to them — with free SSL certificates.

What is Traefik?

Traefik sits in front of your services:

Internet → Traefik → Container A (app.domain.com)
                  → Container B (api.domain.com)
                  → Container C (admin.domain.com)

Key features:

Why Traefik vs Nginx?

Feature Traefik Nginx
Docker integration Native Manual config
Auto SSL Built-in Certbot needed
Service discovery Automatic Manual
Config reload Hot reload Requires restart
Learning curve Moderate Lower
Performance Excellent Excellent

Traefik wins for Docker environments. Nginx for static configs.

VPS Requirements

Traefik is lightweight:

Your VPS specs depend on your services, not Traefik.

Basic Setup

Step 1: Create Network

docker network create traefik-public

Step 2: Create Traefik Config Directory

mkdir -p /opt/traefik
cd /opt/traefik

Step 3: Create Docker Compose

# docker-compose.yml
version: '3.8'

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik.yml:/traefik.yml:ro
      - ./acme.json:/acme.json
      - ./config:/config:ro
    networks:
      - traefik-public
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.rule=Host(`traefik.yourdomain.com`)"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.middlewares=auth"
      - "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xxxxx"

networks:
  traefik-public:
    external: true

Step 4: Create Traefik Config

# traefik.yml
api:
  dashboard: true
  insecure: false

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

  websecure:
    address: ":443"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    network: traefik-public
  file:
    directory: /config
    watch: true

certificatesResolvers:
  letsencrypt:
    acme:
      email: you@yourdomain.com
      storage: /acme.json
      httpChallenge:
        entryPoint: web

Step 5: Create Certificate Storage

touch acme.json
chmod 600 acme.json
mkdir config

Step 6: Generate Dashboard Password

htpasswd -nb admin your-secure-password
# Output: admin:$apr1$...
# Use this in docker-compose.yml, doubling the $ signs

Step 7: Launch Traefik

docker compose up -d

Access dashboard: https://traefik.yourdomain.com

Adding Services

Example: Nginx

# In a separate docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    container_name: nginx
    restart: unless-stopped
    networks:
      - traefik-public
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nginx.rule=Host(`www.yourdomain.com`)"
      - "traefik.http.routers.nginx.entrypoints=websecure"
      - "traefik.http.routers.nginx.tls.certresolver=letsencrypt"

networks:
  traefik-public:
    external: true

That's it! Traefik discovers the container and:

Example: Node.js App

services:
  api:
    build: .
    container_name: api
    networks:
      - traefik-public
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.yourdomain.com`)"
      - "traefik.http.routers.api.entrypoints=websecure"
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"
      - "traefik.http.services.api.loadbalancer.server.port=3000"

networks:
  traefik-public:
    external: true

Note: loadbalancer.server.port specifies the container port.

Middleware

Basic Auth

labels:
  - "traefik.http.middlewares.auth.basicauth.users=user:$$hashed$$password"
  - "traefik.http.routers.admin.middlewares=auth"

Rate Limiting

labels:
  - "traefik.http.middlewares.ratelimit.ratelimit.average=100"
  - "traefik.http.middlewares.ratelimit.ratelimit.burst=50"
  - "traefik.http.routers.api.middlewares=ratelimit"

IP Whitelist

labels:
  - "traefik.http.middlewares.ipwhitelist.ipwhitelist.sourcerange=192.168.1.0/24,10.0.0.0/8"
  - "traefik.http.routers.admin.middlewares=ipwhitelist"

Headers

labels:
  - "traefik.http.middlewares.security.headers.stsSeconds=31536000"
  - "traefik.http.middlewares.security.headers.stsIncludeSubdomains=true"
  - "traefik.http.middlewares.security.headers.contentTypeNosniff=true"
  - "traefik.http.middlewares.security.headers.frameDeny=true"

Redirect

labels:
  - "traefik.http.middlewares.redirect.redirectregex.regex=^https://old.domain.com/(.*)"
  - "traefik.http.middlewares.redirect.redirectregex.replacement=https://new.domain.com/$${1}"

Compress

labels:
  - "traefik.http.middlewares.compress.compress=true"
  - "traefik.http.routers.web.middlewares=compress"

Multiple Domains

Same Container

labels:
  - "traefik.http.routers.web.rule=Host(`domain1.com`) || Host(`domain2.com`)"

With Redirect

labels:
  - "traefik.http.routers.www.rule=Host(`www.domain.com`)"
  - "traefik.http.routers.www.middlewares=redirect-to-apex"
  - "traefik.http.middlewares.redirect-to-apex.redirectregex.regex=^https://www\\.(.+)"
  - "traefik.http.middlewares.redirect-to-apex.redirectregex.replacement=https://$${1}"

Load Balancing

Multiple Containers

services:
  api:
    image: myapi
    deploy:
      replicas: 3
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.domain.com`)"

Traefik automatically load balances across replicas.

Sticky Sessions

labels:
  - "traefik.http.services.api.loadbalancer.sticky.cookie=true"
  - "traefik.http.services.api.loadbalancer.sticky.cookie.name=server_id"

Health Checks

labels:
  - "traefik.http.services.api.loadbalancer.healthcheck.path=/health"
  - "traefik.http.services.api.loadbalancer.healthcheck.interval=10s"

Path-Based Routing

labels:
  - "traefik.http.routers.api.rule=Host(`domain.com`) && PathPrefix(`/api`)"
  - "traefik.http.routers.web.rule=Host(`domain.com`) && PathPrefix(`/`)"

Strip Path Prefix

labels:
  - "traefik.http.middlewares.strip-api.stripprefix.prefixes=/api"
  - "traefik.http.routers.api.middlewares=strip-api"

/api/users becomes /users for the backend.

Wildcard Certificates

For *.domain.com:

# traefik.yml
certificatesResolvers:
  letsencrypt:
    acme:
      email: you@domain.com
      storage: /acme.json
      dnsChallenge:
        provider: cloudflare
# docker-compose.yml
environment:
  - CF_API_EMAIL=you@domain.com
  - CF_API_KEY=your-api-key

Then use:

labels:
  - "traefik.http.routers.web.tls.certresolver=letsencrypt"
  - "traefik.http.routers.web.tls.domains[0].main=domain.com"
  - "traefik.http.routers.web.tls.domains[0].sans=*.domain.com"

File-Based Configuration

For non-Docker services, use file provider:

# /opt/traefik/config/external.yml
http:
  routers:
    external-service:
      rule: "Host(`external.domain.com`)"
      service: external-service
      tls:
        certResolver: letsencrypt

  services:
    external-service:
      loadBalancer:
        servers:
          - url: "http://192.168.1.100:8080"

Traefik watches the config directory and reloads automatically.

Metrics & Monitoring

Enable Metrics

# traefik.yml
metrics:
  prometheus:
    entryPoint: metrics
    buckets:
      - 0.1
      - 0.3
      - 1.2
      - 5.0

entryPoints:
  metrics:
    address: ":8082"

Grafana Dashboard

Use dashboard ID 11462 for Traefik metrics.

Access Logs

# traefik.yml
accessLog:
  filePath: "/var/log/traefik/access.log"
  format: json
  filters:
    statusCodes:
      - "400-599"
  bufferingSize: 100

Mount the log directory:

volumes:
  - ./logs:/var/log/traefik

Troubleshooting

Container Not Discovered

  1. Check network:
docker network inspect traefik-public
  1. Verify labels:
docker inspect container_name | grep -A 50 Labels
  1. Check traefik.enable=true

SSL Not Working

  1. Check ACME log:
docker logs traefik 2>&1 | grep -i acme
  1. Verify acme.json permissions (600)

  2. Ensure port 80 is open for HTTP challenge

502 Bad Gateway

  1. Check container is running
  2. Verify port is correct in labels
  3. Check container logs

View Active Configuration

Dashboard shows all routers, services, and middlewares. Or:

curl http://localhost:8080/api/http/routers

Production Checklist

Best VPS for Traefik

Traefik itself is tiny. Size for your services:

Provider Plan Price Best For
Hetzner CX21 €5.39 5-10 services
Hostinger KVM1 $4.99 Budget setup
Vultr VC2 $12 Global reach

FAQ

Traefik vs Nginx Proxy Manager?

Traefik for Docker-native setups. NPM for simpler GUI-based config.

How many services can Traefik handle?

Hundreds easily. It's designed for microservices at scale.

Is Traefik secure?

Yes. Don't expose the API without auth. Keep updated.

Can I migrate from Nginx?

Yes. Gradual migration is possible — run both temporarily.

Does Traefik support HTTP/3?

Yes, as of v3.0. Enable in entrypoint config.

Summary

Traefik automates what you'd manually configure in Nginx:

Task Nginx Traefik
Add service Edit config, reload Add labels
Get SSL Run certbot Automatic
Load balance Configure upstream Automatic
Remove service Edit config, reload Stop container

For Docker deployments, Traefik is the modern choice. Set it up once, add services with labels forever.

~/traefik-docker-guide/get-started

Ready to get started?

Get the best VPS hosting deal today. Hostinger offers 4GB RAM VPS starting at just $4.99/mo.

Get Hostinger VPS — $4.99/mo

// up to 75% off + free domain included

// related topics

traefik docker traefik setup docker reverse proxy traefik ssl container routing

fordnox

Expert VPS reviews and hosting guides. We test every provider we recommend.

// last updated: February 8, 2026. Disclosure: This article may contain affiliate links.