Traefik

Traefik is a reverse proxy and load balancer whose distinguishing feature is dynamic configuration from the environment. Rather than a static config file listing backends, it watches a provider — the Docker socket, Kubernetes, Consul — and builds its routing from what it finds there.

In practice that means a service declares its own routing in its container labels:

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

Start the container and it is routed. Stop it and the route disappears. No proxy config edit, no reload, no window where the two are out of step.

Why that matters more than it sounds

The traditional pattern keeps routing in one place and the service in another, so adding a service means changing two things owned by potentially different people. Configuration drift between what is running and what the proxy thinks is running is a familiar failure, and it surfaces at the worst moment — during a deployment.

Co-locating routing with the service definition makes drift structurally impossible. That is a real architectural improvement, not a convenience.

Automatic TLS is the other reason to use it. Traefik obtains and renews Let’s Encrypt certificates itself, given an email and a resolver. Certificate expiry is a classic avoidable outage, and removing the renewal step removes it.

What to be careful about

The Docker socket is root. Traefik needs to read it to discover containers, and anything that can write to the Docker socket can start a privileged container and own the host. Mount it read-only, and for anything exposed consider a socket proxy that permits only the read calls Traefik needs. This is the security consideration people skip.

Labels are strings in YAML. The router rule syntax uses backticks, is not validated until Traefik parses it, and a typo produces a route that silently does not match. Debugging usually means the dashboard, which shows what Traefik actually understood — and is worth enabling in development and not exposing in production.

Websockets need no special configuration in Traefik itself, and do need timeouts long enough not to kill idle connections. See websocket patterns.

Against nginx: nginx is faster at raw throughput and better documented, with far more examples for unusual cases. Traefik wins on dynamic environments. For a static set of backends nginx remains a perfectly good answer.

See also: Docker Compose, HTTP, websocket patterns, and Status Alganize.