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
letsencryptdirectory; - the shared
proxynetwork 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.
HostRegexpandPathPrefixno 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
swarmprovider. - The
ipWhiteListmiddleware was renamed toipAllowList.
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=truelabel, theHostrule 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
proxynetwork, 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.


