Traefik’s providers are the key to its dynamic configuration, meaning you don’t have to manually restart Traefik when you add or remove services.
Here’s Traefik in action with Docker, showing how it automatically discovers and configures routes for containers.
# Start a simple web service container
docker run -d --name whoami -p 8080:80 \
traefik/whoami
# Start Traefik with the Docker provider enabled
docker run -d --name traefik -p 80:80 -p 8080:8080 \
-v /var/run/docker.sock:/var/run/docker.sock \
traefik:v2.10 \
--providers.docker=true \
--api.insecure=true \
--log.level=DEBUG
# Now, access whoami through Traefik
curl http://localhost:8080/
When you curl http://localhost:8080/, Traefik, listening on port 80, intercepts the request. It checks its internal routing table, which was automatically populated by the Docker provider observing the whoami container. Traefik forwards the request to the whoami container’s exposed port (8080 in this case).
The core problem Traefik’s providers solve is eliminating the need for manual configuration updates. Instead of editing a static traefik.yml file and restarting Traefik every time you deploy a new microservice or change an existing one, Traefik can watch your infrastructure (Docker, Kubernetes, etc.) and update its configuration on the fly.
Internally, each provider is a watcher. The Docker provider watches the Docker daemon’s event stream. The Kubernetes CRD provider watches the Kubernetes API server for changes to IngressRoute or TraefikService resources. The file provider watches a specified directory or file for changes. When an event occurs – a container starts, a new Kubernetes object is created, or a config file is modified – the provider translates that event into Traefik’s internal configuration model, which includes defining routers, services, middlewares, and TLS options.
Think of routers as the "if this, then that" rules. A router defines conditions (like hostnames, paths, or methods) and what to do when those conditions are met (forward to a specific service). Services are the actual backends – your containers or Kubernetes pods. Middlewares are optional steps that can modify requests or responses before they reach a service or after they leave it, such as adding authentication, rate limiting, or request headers.
Let’s look at the Docker provider in more detail. When Traefik starts with --providers.docker=true, it connects to the Docker daemon. It then subscribes to events like container_start, container_stop, container_die, and network_connect/disconnect. When a container starts, Traefik inspects its labels. These labels are crucial for dynamic configuration. For example, a label like traefik.http.routers.myrouter.rule=Host(\my.example.com`)tells Traefik to create a router namedmyrouterthat will forward requests formy.example.comto this container. The labeltraefik.http.services.myservice.loadbalancer.server.port=80` specifies which port on the container Traefik should send traffic to.
The Kubernetes provider works similarly but interacts with the Kubernetes API. It can watch Ingress resources (for basic compatibility) or, more powerfully, Traefik’s custom resource definitions (CRDs) like IngressRoute and TraefikService. Using CRDs offers more granular control and flexibility, allowing you to define complex routing, load balancing strategies, and middleware chaining directly within Kubernetes manifests. For instance, an IngressRoute manifest would define the entry points, matching rules, and the services to route to, all managed by Kubernetes.
The file provider is the most straightforward. You point Traefik to a directory or a specific file (e.g., --providers.file.directory=/etc/traefik/conf.d or --providers.file.filename=/etc/traefik/traefik.yml). Traefik will then monitor this location for changes. You can define your routers, services, and middlewares in YAML or TOML format within these files. When a file is updated, Traefik automatically reloads its configuration without a restart. This is often used for static configurations or for specific middleware definitions that don’t easily map to dynamic infrastructure events.
A common point of confusion is how Traefik decides which provider to use. If you enable multiple providers (e.g., --providers.docker=true --providers.kubernetesCRD=true), Traefik will merge the configurations from all enabled providers. However, conflicts can arise. For example, if two providers try to define a router with the same name and matching rule, Traefik’s behavior might be to prioritize one based on internal ordering or simply log an error. It’s generally best practice to use providers that are appropriate for your environment – Docker provider for Docker-only deployments, Kubernetes CRD provider for Kubernetes, and file provider for specific, static overrides or initial bootstrap configurations.
The next step in mastering Traefik’s configuration is understanding how to leverage its extensive middleware capabilities to enhance your routing rules.