⚠️ Traduction non officielle - Cette documentation est une traduction communautaire non officielle de Docker.

Routage HTTP avec Traefik

Introduction

Pendant le développement local, il est assez courant d'avoir besoin d'exécuter plusieurs services HTTP. Vous pourriez avoir à la fois une API et une application frontend, un service WireMock pour simuler des points de terminaison de données, ou un visualiseur de base de données (comme phpMyAdmin ou pgAdmin). Dans de nombreuses configurations de développement, ces services sont exposés sur des ports différents, ce qui vous oblige non seulement à vous souvenir de ce qui se trouve sur quel port, mais peut également introduire d'autres problèmes (comme le CORS).

Un proxy inverse peut simplifier considérablement cette configuration en étant le seul service exposé, puis en acheminant les requêtes vers le service approprié en fonction de l'URL de la requête (par chemin ou par nom d'hôte). Traefik est un proxy inverse et un équilibreur de charge moderne et natif du cloud qui facilite le développement et le déploiement d'applications multi-services. Ce guide vous montrera comment utiliser Traefik avec Docker pour améliorer votre environnement de développement.

Dans ce guide, vous apprendrez à :

  1. Démarrer Traefik avec Docker
  2. Configurer des règles de routage pour répartir le trafic entre deux conteneurs
  3. Utiliser Traefik dans un environnement de développement conteneurisé
  4. Utiliser Traefik pour envoyer des requêtes à des charges de travail non conteneurisées

Prérequis

Les prérequis suivants sont nécessaires pour suivre ce guide pratique :

Utiliser Traefik avec Docker

L'une des caractéristiques uniques de Traefik est sa capacité à être configuré de nombreuses manières. Lors de l'utilisation du fournisseur Docker, Traefik obtient sa configuration à partir d'autres conteneurs en cours d'exécution à l'aide d'étiquettes. Traefik surveillera les événements du moteur (pour les démarrages et les arrêts de conteneurs), extraira les étiquettes et mettra à jour sa configuration.

Bien qu'il existe de nombreuses étiquettes surveillées par Traefik, les deux plus courantes seront :

Faisons une démonstration rapide du démarrage de Traefik, puis de la configuration de deux conteneurs supplémentaires pour qu'ils soient accessibles à l'aide de noms d'hôtes différents.

  1. Pour que deux conteneurs puissent communiquer entre eux, ils doivent être sur le même réseau. Créez un réseau nommé traefik-demo à l'aide de la commande docker network create :

    $ docker network create traefik-demo
    
  2. Démarrez un conteneur Traefik à l'aide de la commande suivante. La commande expose Traefik sur le port 80, monte le socket Docker (qui est utilisé pour surveiller les conteneurs afin de mettre à jour la configuration) et passe l'argument --providers.docker pour configurer Traefik afin qu'il utilise le fournisseur Docker.

    $ docker run -d --network=traefik-demo -p 80:80 -v /var/run/docker.sock:/var/run/docker.sock traefik:v3.1.2 --providers.docker
    
  3. Maintenant, démarrez un simple conteneur Nginx et définissez les étiquettes que Traefik surveille pour configurer le routage HTTP. Notez que le conteneur Nginx n'expose aucun port.

    $ docker run -d --network=traefik-demo --label 'traefik.http.routers.nginx.rule=Host(`nginx.localhost`)' nginx
    

    Une fois le conteneur démarré, ouvrez votre navigateur à l'adresse http://nginx.localhost pour voir l'application (tous les navigateurs basés sur Chromium acheminent les requêtes *.localhost localement sans configuration supplémentaire).

  4. Démarrez une deuxième application qui utilisera un nom d'hôte différent.

    $ docker run -d --network=traefik-demo --label 'traefik.http.routers.welcome.rule=Host(`welcome.localhost`)' docker/welcome-to-docker
    

    Une fois le conteneur démarré, ouvrez votre navigateur à l'adresse http://welcome.localhost. Vous devriez voir un site web "Welcome to Docker".

Utiliser Traefik en développement

Maintenant que vous avez expérimenté Traefik, il est temps d'essayer de l'utiliser dans un environnement de développement. Dans cet exemple, vous utiliserez une application d'exemple qui a un frontend et un backend séparés. Cette pile d'applications a la configuration suivante :

  1. Toutes les requêtes vers /api vont au service API
  2. Toutes les autres requêtes vers localhost vont au client frontend
  3. Comme l'application utilise MySQL, db.localhost doit fournir phpMyAdmin pour faciliter l'accès à la base de données pendant le développement
Diagramme d'architecture montrant Traefik acheminant les requêtes vers d'autres conteneurs en fonction du chemin de la requête

L'application est accessible sur GitHub à l'adresse dockersamples/easy-http-routing-with-traefik.

  1. Dans le fichier compose.yaml, Traefik utilise la configuration suivante :

    services:
      proxy:
        image: traefik:v3.1.2
        command: --providers.docker
        ports:
          - 80:80
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock

    Notez qu'il s'agit essentiellement de la même configuration que celle utilisée précédemment, mais maintenant dans une syntaxe Compose.

  2. Le service client a la configuration suivante, qui démarrera le conteneur et lui fournira les étiquettes pour recevoir les requêtes sur localhost.

    services:
      # …
      client:
        image: nginx:alpine
        volumes:
          - "./client:/usr/share/nginx/html"
        labels:
          traefik.http.routers.client.rule: "Host(`localhost`)"
  3. Le service api a une configuration similaire, mais vous remarquerez que la règle de routage a deux conditions - l'hôte doit être "localhost" et le chemin de l'URL doit avoir un préfixe de "/api". Comme cette règle est plus spécifique, Traefik l'évaluera en premier par rapport à la règle du client.

    services:
      # …
      api:
        build: ./dev/api
        volumes:
          - "./api:/var/www/html/api"
        labels:
          traefik.http.routers.api.rule: "Host(`localhost`) && PathPrefix(`/api`)"
  4. Et enfin, le service phpmyadmin est configuré pour recevoir les requêtes pour le nom d'hôte "db.localhost". Le service a également des variables d'environnement définies pour se connecter automatiquement, ce qui facilite un peu l'accès à l'application.

    services:
      # …
      phpmyadmin:
        image: phpmyadmin:5.2.1
        labels:
          traefik.http.routers.db.rule: "Host(`db.localhost`)"
        environment:
          PMA_USER: root
          PMA_PASSWORD: password
  5. Avant de démarrer la pile, arrêtez le conteneur Nginx s'il est toujours en cours d'exécution.

Et c'est tout. Maintenant, il vous suffit de lancer la pile Compose avec un docker compose up et tous les services et applications seront prêts pour le développement.

Envoyer du trafic à des charges de travail non conteneurisées

Dans certaines situations, vous pouvez vouloir transférer des requêtes vers des applications qui ne s'exécutent pas dans des conteneurs. Dans le diagramme d'architecture suivant, la même application qu'auparavant est utilisée, mais les applications API et React s'exécutent maintenant nativement sur la machine hôte.

Un diagramme d'architecture montrant plusieurs composants et le routage entre eux. Traefik est capable d'envoyer des requêtes à des charges de travail à la fois non conteneurisées et conteneurisées

Pour ce faire, Traefik devra utiliser une autre méthode pour se configurer. Le fournisseur de fichiers vous permet de définir les règles de routage dans un document YAML. Voici un exemple de fichier :

http:
  routers:
    native-api:
      rule: "Host(`localhost`) && PathPrefix(`/api`)"
      service: native-api
    native-client:
      rule: "Host(`localhost`)"
      service: native-client

  services:
    native-api:
      loadBalancer:
        servers:
          - url: "http://host.docker.internal:3000/"
    native-client:
      loadBalancer:
        servers:
          - url: "http://host.docker.internal:5173/"

Cette configuration indique que les requêtes pour localhost/api seront transférées à un service nommé native-api, qui transfère ensuite la requête à http://host.docker.internal:3000. Le nom d'hôte host.docker.internal est un nom que Docker Desktop fournit pour envoyer des requêtes à la machine hôte.

Avec ce fichier, le seul changement concerne la configuration Compose pour Traefik. Il y a spécifiquement deux choses qui ont changé :

  1. Le fichier de configuration est monté dans le conteneur Traefik (le chemin de destination exact dépend de vous)
  2. La commande est mise à jour pour ajouter le fournisseur de fichiers et pointer vers l'emplacement du fichier de configuration
services:
  proxy:
    image: traefik:v3.1.2
    command: --providers.docker --providers.file.filename=/config/traefik-config.yaml --api.insecure
    ports:
      - 80:80
      - 8080:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./dev/traefik-config.yaml:/config/traefik-config.yaml

Démarrage de l'application d'exemple

Pour exécuter l'application d'exemple qui transfère les requêtes de Traefik vers des applications s'exécutant nativement, suivez les étapes suivantes :

  1. Si la pile Compose est toujours en cours d'exécution, arrêtez-la avec la commande suivante :

    $ docker compose down
    
  2. Démarrez l'application à l'aide du fichier compose-native.yaml fourni :

    $ docker compose -f compose-native.yaml up
    

    Ouvrir http://localhost renverra un 502 Bad Gateway car les autres applications ne sont pas encore en cours d'exécution.

  3. Démarrez l'API en exécutant les étapes suivantes :

    cd api
    yarn install
    yarn dev
    
  4. Démarrez le frontend en exécutant les étapes suivantes dans un nouveau terminal (en partant de la racine du projet) :

    cd client
    yarn install
    yarn dev
    
  5. Ouvrez l'application à l'adresse http://localhost. Vous devriez voir une application qui récupère un message depuis http://localhost/api/messages. Vous pouvez également ouvrir http://db.localhost pour afficher ou ajuster les messages disponibles directement depuis la base de données Mongo. Traefik s'assurera que les requêtes sont correctement acheminées vers le conteneur ou l'application approprié.

  6. Lorsque vous avez terminé, exécutez docker compose down pour arrêter les conteneurs et arrêtez les applications Yarn en appuyant sur ctrl+c.

Récapitulatif

L'exécution de plusieurs services ne nécessite pas obligatoirement une configuration de port complexe et une bonne mémoire. Avec des outils comme Traefik, il est facile de lancer les services dont vous avez besoin et d'y accéder facilement - que ce soit pour l'application elle-même (comme le frontend et le backend) ou pour des outils de développement supplémentaires (comme phpMyAdmin).