Understand File Provider in Traefik 2
Ever since I started making videos of using Traefik 2, I got a few requests to make a video talking about Traefik 2 configuration in general. As my understanding of this product could be wrong or even misleading, I am very careful NOT to tell people what they SHOULD do, instead I simply provide a working solution for people to explore this product.
Because of the requests I’ve got, I feel like I should know more about this product in case someone ask me. This article is about
file provider
, something I got it working recently.
If you’ve watched my video before, you may remember the providers section I put on my static configuration traefik.yml
as below:
1 | providers: |
Although users can define all setting with just labels, I always prefer using less labels. It looks really messy to have too many labels IMO. That’s why I use a combination of docker with file provider to set up my system previously. Docker and labels are used to define router
,service
and file was used to definemiddleware
.
By using only the file provider to define router
, middleware
and service
does not only help reducing labels but also bring in some extra features like swapping different host names to different services dynamically without the need of restarting your container.
Most settings with file providers are dynamic. In this article, I will focus on how these settings are working together instead of how each settings work. Users need to change the setting to match their environment and applications.
Let’s begin:
Preparations
Static Configuration
We must define entryPoints
and provider
on static configuration traefik.yml
.
You can use my config as a reference for entryPoints
. Based on office documentation, we can use Traefik to either monitor a Single file
or all config files in a directory
with file provider
. It is pretty self-explanatory, examples below:
Single File
1 | providers: |
Directory
1 | providers: |
Dynamic configuration
Let’s see how we use dynamic configuration to replace labels.
Single File
Well, the name says it all. We just put all settings on 1 single file. I found below example from middleware
page.
1 | # As YAML Configuration File |
This setting is pretty straight forward. When clients go to example.com
, Traefik will use foo-add-prefix
middleware on their requests and then direct them to myService
which internal ip address is 127.0.0.1
port 80
.
Directory
If you use directory, you can use multiple config files for settings. For example, router.yml
for router, middleware.yml
for middlewares etc. Below is just an example of the folder structure.
1 | |-- data |
For personal or small websites, single file is sufficient. If you are managing something complicated, it is probably easier to mange your config settings on different files.
Config Example
When we use file provider, we can start the service first, and then define how we want to handle traffic to this service later. Let me use a Nginx service as an example.
Docker-Compose
As you can see I am not using any labels here.
1 | version: '3.7' |
Let’s run docker-compose up -d
to create this container first.
Router
The official document did a good job explaining the router rules. Most of time you just use Host(`example.com`, ...)
to define the host name of this router. If you want route your traffic to a subfolder under the base domain, you can use Host(`example.com`, ...) && Path(`/traefik`)
. In my example, I route all requests of nginx.yourdomain
to nginx-service
and apply a middleware called user-auth
to it.
1 | http: |
Let me compare the labels we would use to achieve the same result. IMO the above config is much more readable.
1 | labels: |
Middleware
You might have seen me using middleware in all my previous articles and videos. I always use dynamic configuration to define my middlewares because I consider middlewares as tools and tools should be easy to use and remove.
You might have noticed I used middleware@file
on label. If you use middleware on dynamic configuration, you can just use it.
Here are the middlewares I am using, please feel free to check and use it.
1 | http: |
Service
I was stuck with defining service before. I did not understand where I can get the url
from demonstrated on official document. I don’t need to worry about what ip address/url it is when I am using labels. It just work when when I am using below labels.
1 | - "traefik.http.routers.nginx-secure.service=nginx-service" |
Even on the offical documentation it says:
In general when configuring a Traefik provider, a service assigned to one (or several) router(s) must be defined as well for the routing to be functional.
There are, however, exceptions when using label-based configurations:
- If a label defines a router (e.g. through a router Rule) and a label defines a service (e.g. implicitly through a loadbalancer server port value), but the router does not specify any service, then that service is automatically assigned to the router.
- If a label defines a router (e.g. through a router Rule) but no service is defined, then a service is automatically created and assigned to the router.
It means even if we don’t use any lables to define any service, Traefik will create and assign the service to my router automatically.
So how should I find the IP address of the service we created? I found two methods and the second method was deprecated on the official forum. I still write it on my article as a reference.
Use container name(Preferred)
Service discovery in docker network is a better option.
When containers are running in the same network, the other containers can find this service via their container name. So when this container restarted with a new ip address, traefik can still find them via their dns name within the network.
Docker Inspect
If you still remember, we started a Nginx container at the beginning of our config example. We can use docker inspect <container_id>
to check its internal ip.
- Let’s use
docker ps
to check all running containers. Let’s say we can see our Nginx container id is41fb11d0047c
- Then we run
docker inspect 41fb11d0047c
. You will get a lot of information about this container, what we care about is itsNetworkSettings
.As we can see, the internal ip address is1
2
3
4
5
6
7
8
9
10
11"NetworkSettings": {
...
"Ports": {
"80/tcp": null
},
...
"IPAddress": "192.168.48.4",
...
}
}
}192.168.48.4
and port80
is opened. Therefore we can define ournginx-service
as below:1
2
3
4
5
6http:
services:
nginx-service:
loadBalancer:
servers:
- url: "http://192.168.96.4:80"
Use Traefik Dashboard
This is NOT recommended on official forum
- Add both docker and file provider on
traefik.yml
.1
2
3
4
5
6providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /configurations/dynamic.yml - After we starting a docker container, we will find this service listed on Traefik Dashboard. We can then grab the internal ip and port from dashboard.
P.S It really took me a few days to test and write this article. I hope did not make too many mistakes and you find this article useful. My next task will be making a video for this article. It is a lot easier to watch a video than reading a long article after all.
Anyway, thanks for reading.
See you next time