Traefik is a reverse proxy built for containers. It watches the Docker API, and when a container starts with the right labels, Traefik automatically routes a domain to it and obtains a Let’s Encrypt certificate. Add a new app, and its HTTPS site is live — no proxy config to edit.
1. Traefik with Docker Compose
mkdir -p ~/traefik && cd ~/traefik
touch acme.json && chmod 600 acme.json
docker network create proxy
compose.yaml:
services:
traefik:
image: traefik:v3.4
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
- [email protected]
- --certificatesresolvers.le.acme.storage=/acme.json
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/acme.json
networks:
- proxy
networks:
proxy:
external: true
docker compose up -d
docker compose logs -f traefik
Key settings:
exposedbydefault=false— only containers withtraefik.enable=trueare published. Without it, every container becomes reachable.- The
webentrypoint redirects everything to HTTPS. acme.jsonstores certificates; it must bechmod 600.
Check the current Traefik version; v3 changed some label and rule syntax compared with v2.
2. Route a container with labels
Any app on the proxy network:
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
Point DNS for whoami.example.com at the server and run docker compose up -d. Within seconds Traefik obtains a certificate and serves the site over HTTPS.
If the container listens on a non-default or multiple ports, tell Traefik which:
- traefik.http.services.whoami.loadbalancer.server.port=8080
The app needs no published ports — Traefik reaches it over the Docker network, so it isn’t exposed directly.
3. Middlewares
Middlewares modify requests. Basic authentication for an admin tool:
echo $(htpasswd -nB admin) | sed -e 's/\$/\$\$/g'
labels:
- traefik.http.middlewares.auth.basicauth.users=admin:$$2y$$05$$…
- traefik.http.routers.tool.middlewares=auth
($ must be doubled in Compose files.) Other useful middlewares: ipallowlist (restrict by IP), ratelimit, headers (security headers, HSTS), redirectregex, stripprefix.
4. The dashboard (carefully)
The dashboard shows routers, services and middlewares — very helpful for debugging. Enable it with --api.dashboard=true and expose it through a router with authentication:
labels:
- traefik.enable=true
- traefik.http.routers.dash.rule=Host(`traefik.example.com`)
- traefik.http.routers.dash.service=api@internal
- traefik.http.routers.dash.entrypoints=websecure
- traefik.http.routers.dash.tls.certresolver=le
- traefik.http.routers.dash.middlewares=auth
Never expose it without authentication or an IP allow-list.
5. Wildcard certificates via DNS challenge
For many subdomains or services not reachable on port 80, use a DNS challenge:
- --certificatesresolvers.le.acme.dnschallenge.provider=cloudflare
environment:
CF_DNS_API_TOKEN: ${CF_DNS_API_TOKEN}
And on a router: tls.domains[0].main=example.com, tls.domains[0].sans=*.example.com.
Security notes
- Mounting the Docker socket (even read-only) gives Traefik powerful access. Consider a socket proxy (e.g. a container exposing only read-only API endpoints) between Traefik and Docker.
- Keep Traefik updated.
- Only ports 80/443 need to be public.
Troubleshooting
- 404 page not found — no router matched: check the
Host()rule,traefik.enable=true, and that the container is on theproxynetwork. - Bad Gateway — wrong service port, or Traefik and the app don’t share a network.
- Self-signed “TRAEFIK DEFAULT CERT” — certificate issuance failed: check logs, DNS and that port 80 reaches Traefik.
Traefik vs alternatives
- Nginx Proxy Manager — web UI, click-to-configure.
- Caddy — simple config file, automatic HTTPS.
- Plain Nginx — maximum control.
Traefik is ideal when containers come and go frequently. A Docker VPS running Traefik can host dozens of apps behind one IP.