Traefik
Traefik est la porte d'entrée de toute l'infrastructure. Il tourne sur tm-prod, écoute les ports 80 et 443, et transmet chaque requête au bon service selon le nom de domaine.
Le conteneur : traefik/docker-compose.yml
services:
traefik:
image: traefik:v3.3
container_name: timemanager-traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./traefik.yml:/traefik.yml:ro
- ./dynamic:/dynamic:ro
- ./acme.json:/acme.json
networks:
- timemanager
networks:
timemanager:
external: true| Volume | Rôle |
|---|---|
traefik.yml | La configuration générale, en lecture seule (ro) |
dynamic/ | Les routes, en lecture seule |
acme.json | Les certificats. Traefik doit pouvoir y écrire. |
Traefik est sur le réseau timemanager : il voit timemanager-front et timemanager-back par leur nom, mais pas la base de données.
Pas de docker.sock
Beaucoup d'installations donnent à Traefik l'accès à Docker pour découvrir les conteneurs tout seul. Ici les routes sont écrites dans des fichiers : Traefik n'a aucun accès à Docker, ce qui réduit les risques.
La configuration générale : traefik/traefik.yml
api:
dashboard: false
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: <adresse de contact>
storage: /acme.json
httpChallenge:
entryPoint: web
providers:
file:
directory: /dynamic
watch: true
log:
level: INFO
accessLog: {}| Partie | Ce qu'elle fait |
|---|---|
api.dashboard: false | Le tableau de bord de Traefik est désactivé (rien à exposer) |
entryPoints.web | Écoute le port 80 et redirige tout vers HTTPS |
entryPoints.websecure | Écoute le port 443 |
certificatesResolvers.letsencrypt | Comment obtenir les certificats (voir plus bas) |
providers.file | Les routes sont dans /dynamic, et watch: true les recharge dès qu'un fichier change |
log, accessLog | Les journaux, et une ligne par requête reçue |
Les certificats HTTPS
Traefik obtient un certificat Let's Encrypt pour chaque domaine, automatiquement :
C'est le défi HTTP (httpChallenge) : Let's Encrypt vérifie qu'on contrôle le domaine en demandant un fichier sur le port 80. C'est pour ça que le port 80 doit rester ouvert, même si tout est redirigé vers HTTPS.
Traefik renouvelle les certificats tout seul avant leur expiration. L'email sert à recevoir les alertes de Let's Encrypt.
Les routes : traefik/dynamic/
Un fichier par service. Exemple, api.yml :
http:
routers:
api:
rule: "Host(`api.time.jostud.com`)"
entryPoints:
- websecure
tls:
certResolver: letsencrypt
service: api
services:
api:
loadBalancer:
servers:
- url: "http://timemanager-back:4000"| Élément | Sens |
|---|---|
routers.api.rule | Cette route s'applique aux requêtes pour ce domaine |
entryPoints: websecure | Seulement en HTTPS |
tls.certResolver | Le certificat vient de Let's Encrypt |
service: api | Où envoyer la requête |
services.api...url | L'adresse réelle du service. Entre Traefik et le service, c'est du HTTP simple, à l'intérieur de la machine ou du réseau privé. |
| Fichier | Domaine | Vers |
|---|---|---|
api.yml | api.time.jostud.com | http://timemanager-back:4000 |
frontend.yml | time.jostud.com | http://timemanager-front:8080 |
docs.yml | docs.time.jostud.com | http://timemanager-docs:8080 |
jenkins.yml | ci.time.jostud.com | http://10.132.0.3:8080 |
Ajouter un service
- Faire pointer le nouveau domaine vers l'IP publique de tm-prod.
- Créer
traefik/dynamic/mon-service.ymlsur le modèle deapi.yml. - Le déployer :
ansible-playbook playbook.yml --tags traefik --ask-vault-pass.
Grâce à watch: true, Traefik prend en compte le fichier sans redémarrer. Au premier appel du domaine, il demande le certificat.