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?
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:
- Auto-discovery — Detects new containers
- Auto-SSL — Let’s Encrypt integration
- Load balancing — Multiple containers per service
- Middleware — Auth, rate limiting, headers
- Dashboard — Visual service overview
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 (see our Nginx reverse proxy guide).
VPS Requirements
Traefik is lightweight:
- 1 vCPU
- 512MB RAM (for Traefik itself)
- Ports 80, 443
Your VPS specs depend on your services, not Traefik. Check our best VPS for Docker guide for sizing recommendations.
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:
- Routes
www.yourdomain.comto it - Gets SSL certificate automatically
- Handles HTTPS termination
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. For a full Grafana monitoring setup, see our dedicated guide.
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
- Check network:
docker network inspect traefik-public
- Verify labels:
docker inspect container_name | grep -A 50 Labels
- Check
traefik.enable=true
SSL Not Working
- Check ACME log:
docker logs traefik 2>&1 | grep -i acme
-
Verify acme.json permissions (600)
-
Ensure port 80 is open for HTTP challenge
502 Bad Gateway
- Check container is running
- Verify port is correct in labels
- Check container logs
View Active Configuration
Dashboard shows all routers, services, and middlewares. Or:
curl http://localhost:8080/api/http/routers
Production Checklist
- Dashboard protected with auth
- acme.json has 600 permissions
- Access logs enabled
- Metrics for monitoring
- Health checks configured
- Rate limiting on public APIs
- Security headers middleware
- Proper network isolation
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. For a full deployment workflow, pair it with Docker Compose.
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
// related guides
$1 VPS Hosting 2026: Cheapest VPS Servers Starting at $1/Month
Looking for $1 VPS hosting? Compare the cheapest VPS providers starting from $1-3/month. Real specs, no hidden fees, honest reviews of budget VPS options.
tutorialCaddy Reverse Proxy Guide 2026: Automatic HTTPS Made Easy
Set up Caddy as a reverse proxy with automatic HTTPS, zero-config SSL, and simple Caddyfile syntax. Complete VPS deployment guide.
tutorialCloudflare Tunnel VPS Guide 2026: Expose Services Without Opening Ports
Set up Cloudflare Tunnel on your VPS to expose web apps securely without opening ports or revealing your server IP. Complete guide with Docker and DNS config.
tutorialCoolify VPS Setup Guide 2026: Self-Hosted Vercel Alternative
Deploy Coolify on your VPS for a self-hosted Vercel/Netlify experience. Complete setup guide with Docker, SSL, and app deployments.
Andrius Putna
I am Andrius Putna. Geek. Since early 2000 in love tinkering with web technologies. Now AI. Bridging business and technology to drive meaningful impact. Combining expertise in customer experience, technology, and business strategy to deliver valuable insights. Father, open-source contributor, investor, 2xIronman, MBA graduate.
// last updated: February 8, 2026. Disclosure: This article may contain affiliate links.