Aller au contenu

🔀 Traefik

Présentation

Traefik est utilisé comme reverse proxy et gestionnaire HTTPS pour les services Docker exposés sur Internet ou sur le réseau local.

Il permet notamment de :

  • recevoir les requêtes HTTP/HTTPS ;
  • sélectionner le bon conteneur en fonction du nom de domaine ;
  • gérer les certificats TLS Let's Encrypt ;
  • rediriger automatiquement HTTP vers HTTPS ;
  • éviter d'exposer directement les ports des différents services ;
  • découvrir automatiquement les services Docker grâce aux labels.

Architecture

L'architecture actuelle repose sur le principe suivant :

                         Internet / LAN
                     docs.services.alin.be
                    ┌──────────────────┐
                    │     Traefik      │
                    │                  │
                    │  :80   → web     │
                    │  :443  → websecure│
                    └────────┬─────────┘
                      traefik-proxy
          ┌──────────────────┼──────────────────┐
          │                  │                  │
          ▼                  ▼                  ▼
   Documentation       Home Assistant      Autres services
      :80                  :8123               ...

Les applications n'ont donc généralement pas besoin d'être directement accessibles depuis Internet.

Traefik reçoit la requête et la transmet au bon conteneur.


🌐 Domaines

Le domaine principal utilisé est :

alin.be

Les services sont exposés sous le domaine :

*.services.alin.be

Par exemple :

docs.services.alin.be

Le DNS est géré chez OVH.


🔐 HTTPS

Traefik utilise Let's Encrypt pour générer les certificats TLS.

Le certificat du site de documentation est par exemple :

docs.services.alin.be

Les certificats sont renouvelés automatiquement par Traefik.

Le mécanisme ACME utilisé est le DNS Challenge, avec le fournisseur DNS OVH.

Traefik
   ├── ACME
   ├── Let's Encrypt
   └── OVH DNS

Le DNS Challenge permet à Traefik de prouver qu'il contrôle le domaine en créant temporairement les enregistrements DNS nécessaires.


🚪 Entrypoints

Les deux entrypoints principaux sont :

Entrypoint Port Utilisation
web 80 HTTP
websecure 443 HTTPS

Le fonctionnement habituel est :

HTTP :80
redirection HTTPS
HTTPS :443

Le middleware utilisé pour la redirection est :

redirect-to-https@file

🐳 Réseau Docker

Les services qui doivent être accessibles par Traefik sont connectés au réseau Docker :

traefik-proxy

Ce réseau permet à Traefik de communiquer directement avec les conteneurs.

Exemple :

networks:
  traefik-proxy:
    external: true

Et pour un service :

services:

  documentation:
    networks:
      - traefik-proxy

Le label suivant indique à Traefik quel réseau utiliser :

labels:
  - "traefik.docker.network=traefik-proxy"

🏷️ Labels Docker

Traefik utilise les labels Docker pour savoir comment publier un service.

Exemple pour le site de documentation :

labels:

  - "traefik.enable=true"
  - "traefik.docker.network=traefik-proxy"

  # HTTP
  - "traefik.http.routers.documentation-http.rule=Host(`docs.services.alin.be`)"
  - "traefik.http.routers.documentation-http.entrypoints=web"
  - "traefik.http.routers.documentation-http.middlewares=redirect-to-https@file"

  # HTTPS
  - "traefik.http.routers.documentation.rule=Host(`docs.services.alin.be`)"
  - "traefik.http.routers.documentation.entrypoints=websecure"
  - "traefik.http.routers.documentation.tls=true"
  - "traefik.http.routers.documentation.tls.certresolver=myresolver"

  # Port interne du conteneur
  - "traefik.http.services.documentation.loadbalancer.server.port=80"

🔎 Fonctionnement des labels

Activation

traefik.enable=true

Indique à Traefik que le conteneur doit être pris en compte.


Réseau

traefik.docker.network=traefik-proxy

Indique à Traefik de communiquer avec le conteneur via :

traefik-proxy

Règle de routage

traefik.http.routers.documentation.rule=Host(`docs.services.alin.be`)

Cela signifie :

Si quelqu'un demande docs.services.alin.be, envoyer la requête vers ce service.


Entrypoint HTTP

traefik.http.routers.documentation-http.entrypoints=web

Le routeur écoute sur :

:80

Entrypoint HTTPS

traefik.http.routers.documentation.entrypoints=websecure

Le routeur écoute sur :

:443

TLS

traefik.http.routers.documentation.tls=true

Active HTTPS pour le routeur.


Certificat Let's Encrypt

traefik.http.routers.documentation.tls.certresolver=myresolver

Indique à Traefik d'utiliser le resolver ACME :

myresolver

Port interne

traefik.http.services.documentation.loadbalancer.server.port=80

C'est un point important.

Cela ne signifie pas que le port 80 doit être publié sur l'hôte.

Cela signifie simplement que Traefik doit contacter le conteneur sur son port interne :

Traefik
   │ HTTP
documentation:80

🔄 Exemple complet

Voici le modèle actuellement utilisé pour la documentation :

services:

  documentation:

    build:
      context: .
      dockerfile: Dockerfile

    container_name: documentation

    restart: unless-stopped

    networks:
      - traefik-proxy

    labels:

      - "traefik.enable=true"
      - "traefik.docker.network=traefik-proxy"

      # HTTP
      - "traefik.http.routers.documentation-http.rule=Host(`docs.services.alin.be`)"
      - "traefik.http.routers.documentation-http.entrypoints=web"
      - "traefik.http.routers.documentation-http.middlewares=redirect-to-https@file"

      # HTTPS
      - "traefik.http.routers.documentation.rule=Host(`docs.services.alin.be`)"
      - "traefik.http.routers.documentation.entrypoints=websecure"
      - "traefik.http.routers.documentation.tls=true"
      - "traefik.http.routers.documentation.tls.certresolver=myresolver"

      # Nginx
      - "traefik.http.services.documentation.loadbalancer.server.port=80"


networks:

  traefik-proxy:
    external: true

🧪 Vérification

Vérifier que Traefik fonctionne

docker ps | grep traefik

Vérifier le réseau

docker network inspect traefik-proxy

Le conteneur concerné doit apparaître dans les conteneurs connectés au réseau.


Vérifier la configuration du conteneur

docker inspect documentation

Pour afficher uniquement les labels :

docker inspect documentation \
  --format '{{json .Config.Labels}}' | jq

Tester le site

curl -I https://docs.services.alin.be

On doit obtenir une réponse HTTP du serveur.


🔧 Commandes utiles

Voir les conteneurs Traefik

docker ps | grep traefik

Voir les logs

docker logs traefik

Ou en temps réel :

docker logs -f traefik

Voir les derniers logs

docker logs --tail 100 traefik

Inspecter le réseau

docker network inspect traefik-proxy

Vérifier les labels d'un service

docker inspect <conteneur> \
  --format '{{json .Config.Labels}}' | jq

⚠️ Problèmes fréquents

404 Traefik

Un 404 de Traefik signifie généralement que la requête n'a pas trouvé de routeur correspondant.

Vérifier :

traefik.http.routers.<nom>.rule=Host(`...`)

et :

traefik.http.routers.<nom>.entrypoints=websecure

Vérifier également que le domaine utilisé dans le navigateur correspond exactement au Host().


Bad Gateway

Un 502 Bad Gateway indique généralement que Traefik trouve le routeur mais ne parvient pas à contacter le conteneur.

Vérifier :

traefik.docker.network=traefik-proxy

et :

traefik.http.services.<nom>.loadbalancer.server.port=80

Puis :

docker network inspect traefik-proxy

Les deux conteneurs doivent être sur le même réseau.


Certificat non généré

Vérifier les logs :

docker logs traefik | grep -i acme

ou :

docker logs traefik | grep -Ei 'acme|certificate|challenge|letsencrypt'

Avec le DNS Challenge OVH, vérifier également que les identifiants/API OVH utilisés par Traefik permettent de modifier les zones DNS.


🧭 Principe à retenir

Pour ajouter un nouveau service derrière Traefik, il faut généralement :

1. Créer le conteneur
2. Le connecter à traefik-proxy
3. Ajouter les labels Traefik
4. Créer le DNS du domaine
5. Traefik détecte le service
6. Let's Encrypt fournit le certificat
7. HTTPS → conteneur

Le service n'a donc pas nécessairement besoin de publier un port sur l'hôte.

Par exemple, pour un service écoutant sur le port 8080 :

Internet
   │ HTTPS :443
Traefik
   │ traefik-proxy
service:8080

Le port 8080 peut rester uniquement accessible à l'intérieur du réseau Docker.