technique:docker:general:traefik

Traefik, un reverse-proxy pour Docker

Une des pièces centrales de l’infrastructure des services de Picasoft est Traefik.

Note:

Sur chaque machine, Picasoft héberge plusieurs services web accessibles via une URL. Lors de la consultation sur un navigateur web, cette URL est traduite en adresse IP (grâce au DNS), et permet de trouver la machine qui correspond à l’URL.

Chaque service tourne dans un conteneur Docker. En prenant un exemple, la situation est la suivante :

Le navigateur contacte naturellement le port 443 car l’URL est en HTTPS, dans cet exemple.

Question:

Comment est-ce-que la machine sait quel conteneur correspond à quelle URL ?

En réalité, elle n’a aucun moyen de le savoir.

Question:

Comment faire ?

Une technique traditionnelle, lorsque plusieurs services tournent sur une même machine et doivent être accessibles via Internet, est d’utiliser les ports pour la destination. Ainsi, chaque conteneur écoute sur un port particulier de la machine. Par exemple, on aurait la situation suivante :

Ainsi, chaque conteneur écoute sur un port spécifique :

  • team.picasoft.net:4000 envoie sur le port 4000 de la machine, sur lequel le conteneur Mattermost écoute
  • pad.picasoft.net:5000 envoie sur le port 5000 de la machine, sur lequel le conteneur Mattermost écoute

Question:

Quel est le problème avec cette configuration ?

C’est une solution simple, néanmoins elle nécessite d’utiliser les ports dans l’URL, et ce n’est vraiment pas pratique pour les utilisateurices. Les sites web que l’on consulte tous les jours n’ont pas de numero de prot dans leur URL, en général.

L’autre technique traditionnelle, c’est d’utiliser un reverse proxy.

  • Un proxy est un serveur vers lequel sont redirigées toutes les requêtes qui sortent d’un ordinateur (par exemple, dans une entreprise, une université…)
  • Un reverse proxy est un serveur vers lequel sont redirigées toutes les requêtes qui entrent vers un ordinateur.

L’idée est donc qu’un reverse proxy écoute sur les port 80 et 443 (qui n’ont pas besoin d’être spécifiés dans l’URL), et qu’il redirige automatiquement vers le bon conteneur, grâce à l’URL de la requête.

Question:

Comment associer une URL à un conteneur ?

Il y a plusieurs solutions. nginx peut tout à faire être utilisé comme reverse proxy. L’inconvénient, c’est qu’il va falloir lui fournir une configuration statique qui associe une URL à un conteneur, et cette configuration devra être modifiée à chaque nouveau service. Il faudra aussi gérer les certificats SSL pour chaque service, par exemple.

C’est pourquoi nous utilisons Traefik, un outil clé en main pour Docker. Traefik fonctionne comme un reverse proxy traditionnel, mais ajoute quelques fonctionnalités bien pratiques :

  • L’association entre URL et conteneur se fait grâce aux labels Docker, ce qui évite de modifier la configuration du reverse-proxy à l’ajout d’un nouveau service.
  • Traefik découvre automatiquement les nouveaux services en “surveillant” Docker, regarde les labels, et crée des routes automatiquement
  • Traefik gère automatiquement la création et le renouvellement des certificats des services
  • Comme tout reverse-proxy, on peut lui demander d’ajouter des headers de sécurité dans les requêtes HTTP

En somme, pour ajouter un nouveau service accessible depuis internet via HTTPS, il suffit d’ajouter quelques labels sur le conteneur, et à son lancement, il est accessible automagiquement, sans configuration supplémentaire.

Lien:

Pour les curieux.ses, une explication de la configuration est aussi disponible sur la page de migration vers Traefik v2.

On ne présente pas ici la manière de configurer Traefik, qui évolue au fil du temps, mais les choix qui ont été faits et les points de vigilance.

Traefik permet de sécuriser les services web en établissant une connexion TLS (HTTPS) entre les clients et lui. Il communique ensuite avec les conteneurs sur le réseau privé Docker, en clair (HTTP). Il est donc fondamental qu’il soit bien sécurisé. En particulier, voici quelques options de configuration qui ont été ajoutées :

  • Forcer à rediriger les requêtes HTTP vers HTTPS.
  • Utilisation de Let’s Encrypt pour créer et renouveller automatiquement les certificats des services.
  • Restriction de la version de TLS minimale (actuellement, 1.2).
  • Restriction des algorithmes de chiffrement utilisés (ciphers), pour éviter les plus faibles tout en garantissant une compatibilité avec la plupart des appareils.
  • Injection de headers de sécurité dans toutes les requêtes et réponses, permettant de limiter les risques d’attaques classiques (XSS, MITM, etc).

Traefik est aussi configuré pour compresser l’ensemble des flux qui transitent par son biais, sauf les flux de streaming (e.g. vidéo…).

Traefik se trouve dans le réseau Docker appelé proxy. Il inspecte tous les conteneurs de ce réseau et décide s’il doit router vers ces conteneurs, en fonction de leurs labels.

Attention:

Tout conteneur qui ne se trouve pas dans le réseau proxy ne sera jamais pris en compte par Traefik.

  • technique/docker/general/traefik.txt
  • de qduchemi