A week ago I decided to play around with Traefik because it seems to be pretty popular for Docker apps since it provides Docker support out of the box. I'm still amazed how easy it was to set it up so I decided to share my experience here in a series of posts.
Today's post will present my Traefik docker-compose.yml from my Ansible role which I use for automatic configurations of my web servers. It basically consists of a systemd service that simply spins up a Traefik Docker service via docker-compose.
Traefik provides mutliple ways to specify its configuration:
In this post I will only focus on CLI commands because those can be directly used within a docker-compose.yml file.
There are 2 types of configurations in Traefik: static and dynamic.
The Traefik documentation always displays the CLI version for static ones. These ones you just append to the command: section in your compose file, e.g.:
...
command:
- --entrypoints.websecure.address=:443
- --entrypoints.web.address=:80
...
Dynamic configurations can be specified via the labels: section in a compose file, e.g.:
...
labels:
- "traefik.http.routers.traefik.rule=Host(`example.com`)"
It's especially this label-approach which made the transition from Nginx to Traefik extremely easy. Once I had the Traefik container running, all it took me to do on my remaining Docker web apps was to update their compose file by adding a few labels and restart the services. Unfortunately the documentation regarding the labels-syntax is not really documented. However, it can be guessed from the YAML/TOML version.
Also note, there are two pretty good Traefik blog posts introducing Traefik 2.0 with Docker:
I suggest to read to through these articles since my article here is just a shorter version of those (I used those articles myself to create my Traefik container below).
I will jump right into it and present my compose file before explaining the most important parts:
version: "3.8"
services:
traefik:
container_name: traefik
image: "{{ traefik_img }}"
command:
- --entrypoints.websecure.address=:443
- --entrypoints.web.address=:80
- --providers.docker=true
- --api
- --certificatesresolvers.le.acme.email=mail@example.com
- --certificatesresolvers.le.acme.storage=/acme/acme.json
- --certificatesresolvers.le.acme.tlschallenge=true
ports:
- "80:80"
- "443:443"
networks:
- traefik
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "$PWD/acme:/acme"
labels:
# Dashboard
- "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.middlewares=admin"
- "traefik.http.routers.traefik.tls.certresolver=le"
- "traefik.http.middlewares.admin.basicauth.users=userXY:pwXY"
# global redirect to https
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.redirs.entrypoints=web"
- "traefik.http.routers.redirs.middlewares=redirect-to-https"
networks:
traefik:
name: traefik
The static configuration (under the command: seciton) specifies to
That's it regarding the static configuration. We now just provide a few additional dynamic configs as labels. We tell it to
This would be already enough to have Traefik up and running with its dashboard published at traefik.example.com. However, because I already had a running Nginx reverse-proxy that redirected all http requests to https I wanted to have the same settings in Traefik. That what the last block of labels does which is marked with the corresponding inline-comment.
In a next post, I will share how I only had to set a few labels to my already existing docker-compose.yml file (that actually contains the Docker services running this blog / website) in order to finalize the migration from Nginx to Traefik.