Traefik is an open-source reverse proxy and load balancer designed for modern cloud-native applications—especially those running in containers.
What that actually means
Think of Traefik as a smart traffic controller sitting in front of your apps:
- It receives incoming requests (like someone visiting your website)
- Then routes them to the correct service (e.g., your API, frontend, or another container)
- It can also balance traffic across multiple instances of the same service
Key features
Automatic service discovery
Traefik integrates directly with tools like:
- Docker
- Kubernetes
It automatically detects new containers/services and routes traffic to them—no manual config needed.
Built-in HTTPS (SSL/TLS)
- Automatically generates and renews certificates using Let’s Encrypt
- Handles HTTPS setup for you (no manual certificate management)
Load balancing
- Distributes requests across multiple instances
- Helps keep your app fast and available
Dynamic configuration
- Updates routes in real time when services start/stop
- No restarts required
Dashboard & monitoring
- Web UI shows routes, services, and traffic
- Useful for debugging and observability
Simple example (Docker)
If you run a container with labels like:
labels: - "traefik.http.routers.myapp.rule=Host(`myapp.local`)"
Traefik will:
- Detect the container
- Create a route for
myapp.local - Start sending traffic there automatically
When people use Traefik
- Microservices architectures
- Docker or Kubernetes setups
- Hosting multiple apps on one server
- Replacing tools like:
- NGINX
- HAProxy
In one sentence
Traefik is a modern, automatic reverse proxy that makes routing traffic to containerized apps simple and dynamic.
Here’s a small working Docker Compose example you can run locally. It follows Traefik’s current Docker quick-start pattern: Traefik listens to Docker, exposes port 80 for app traffic and 8080 for the dashboard, and routes a sample whoami container using labels. (Traefik Docs)
version: "3.9"services: traefik: image: traefik:v3.0 container_name: traefik command: - "--api.insecure=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entryPoints.web.address=:80" ports: - "80:80" - "8080:8080" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" whoami: image: traefik/whoami container_name: whoami labels: - "traefik.enable=true" - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)" - "traefik.http.routers.whoami.entrypoints=web"
Run it with:
docker compose up -d
Then open:
http://whoami.localhost→ sample apphttp://localhost:8080→ Traefik dashboard
That hostname rule is the key idea: Traefik reads the Docker labels and creates a router so requests for whoami.localhost go to the whoami container. Traefik hot-reloads this dynamic routing config from Docker without restarting. (Traefik Docs)
How to read the important lines:
--providers.docker=truetells Traefik to watch Docker for containers/services. (Traefik Docs)--providers.docker.exposedbydefault=falsemeans only containers withtraefik.enable=trueget exposed. (Traefik Docs)--entryPoints.web.address=:80creates an HTTP entrypoint on port 80. (Traefik Docs)traefik.http.routers.whoami.rule=Host(\whoami.localhost`)` matches incoming requests by hostname. (Traefik Docs)
A more realistic example is routing two apps:
version: "3.9"services: traefik: image: traefik:v3.0 command: - "--api.insecure=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entryPoints.web.address=:80" ports: - "80:80" - "8080:8080" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" app1: image: traefik/whoami labels: - "traefik.enable=true" - "traefik.http.routers.app1.rule=Host(`app1.localhost`)" - "traefik.http.routers.app1.entrypoints=web" app2: image: traefik/whoami labels: - "traefik.enable=true" - "traefik.http.routers.app2.rule=Host(`app2.localhost`)" - "traefik.http.routers.app2.entrypoints=web"
Then:
http://app1.localhost→ app1http://app2.localhost→ app2
That is basically the Traefik workflow: define a service, add labels, and Traefik discovers it automatically. The official docs also note that when both containers are in the same Compose file, Docker’s default network is enough for Traefik to reach them. (Traefik Docs)
A couple of useful notes:
- The dashboard setting shown here is insecure and meant for local learning, not production. (Traefik Docs)
- For production, people usually add TLS/HTTPS and often Let’s Encrypt certificate automation through Traefik’s config. The routing and certificates are part of Traefik’s dynamic config model. (Traefik Docs)
Want me to show the same thing with HTTPS + Let’s Encrypt, or a Kubernetes Ingress example?
Here’s a real HTTPS + Let’s Encrypt Docker Compose setup for Traefik.
It uses the HTTP-01 challenge, which means your server must be publicly reachable on ports 80 and 443, and your domain’s DNS must point at that server. Traefik’s docs also note that certificate resolvers are defined in static config, the router must have TLS enabled, and the router references the resolver by name. (Traefik Docs)
version: "3.9"services: traefik: image: traefik:v3.4 container_name: traefik command: - "--api.dashboard=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" # entrypoints - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" # redirect http -> https - "--entrypoints.web.http.redirections.entrypoint.to=websecure" - "--entrypoints.web.http.redirections.entrypoint.scheme=https" # lets encrypt - "--certificatesresolvers.le.acme.email=you@example.com" - "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json" - "--certificatesresolvers.le.acme.httpchallenge=true" - "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web" ports: - "80:80" - "443:443" - "8080:8080" # optional dashboard volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" - "./letsencrypt:/letsencrypt" app: image: traefik/whoami container_name: whoami labels: - "traefik.enable=true" # router - "traefik.http.routers.app.rule=Host(`whoami.yourdomain.com`)" - "traefik.http.routers.app.entrypoints=websecure" - "traefik.http.routers.app.tls=true" - "traefik.http.routers.app.tls.certresolver=le"
Then run:
mkdir -p letsencrypttouch letsencrypt/acme.jsonchmod 600 letsencrypt/acme.jsondocker compose up -d
Then open:
https://whoami.yourdomain.comhttp://whoami.yourdomain.comwill redirect to HTTPS
Why this works:
providers.docker=truemakes Traefik watch Docker containers and labels. (Traefik Docs)entrypoints.webandentrypoints.websecurecreate listeners on ports 80 and 443. (Traefik Docs)certificatesresolvers.le.acme.*configures Let’s Encrypt and stores certs inacme.json. (Traefik Docs)tls.certresolver=letells that router to request and renew a cert through theleresolver. (Traefik Docs)
A couple of important gotchas:
- Replace
you@example.comwith your real email. - Replace
whoami.yourdomain.comwith a real domain/subdomain you control. - That hostname needs an A or AAAA record pointing to your server. Traefik’s docs say ACME domains must point to Traefik. (Traefik Docs)
- Port
8080is just for the dashboard. Don’t leave it openly exposed on the internet unless you secure it. (Traefik Docs)
For Kubernetes, the usual Traefik-native route is an IngressRoute or standard Ingress; Traefik also documents a working Kubernetes + Let’s Encrypt example with CRDs. (Traefik Docs)