Objectifs

  • Configurer et lancer localement un reverse proxy Traefik dockerisé doté de certificats TLS générés automatiquement
  • Déployer le tout sur un nom de domaine réel

Introduction rapide

Traefik est un reverse proxy HTTP moderne doublé d’un load balancer qui facilite le déploiement de microservices. Il est conçu pour s’intégrer parfaitement à vos composants d’infrastructure existants, et devient particulièrement puissant lorsqu’il est utilisé avec Docker.

Au cœur de son fonctionnement, Traefik procède avec une capacité de découverte dynamique de vos services (conteneurs) et leur achemine les requêtes correspondantes. Plutôt que de configurer manuellement chaque endpoint, Traefik surveille votre démon Docker (ou d’autres orchestrateurs comme Kubernetes, Swarm, Mesos, etc.) pour détecter les changements. Lorsqu’un nouveau conteneur est lancé ou qu’un conteneur existant est arrêté, Traefik met automatiquement à jour ses règles de routage. Vous pouvez consulter la documentation officielle ici : https://doc.traefik.io/traefik/

Diagramme vue d'ensemble de la relation Traefik/Docker Vue d'ensemble de la relation Traefik/Docker


Code source

Vous trouverez ici le code source complet pour un reverse proxy Traefik prêt à l’emploi, avec génération automatique de certificats TLS : https://github.com/a-naitslimane/anaitslimane.article.reverse-proxy-traefik-docker.git


Note:

Il existe de nombreuses façons d’exécuter/déployer des conteneurs Docker. Ici, j’utiliserai exclusivement docker compose.

Configuration locale

Prérequis :

  • Docker et Docker Compose installés sur votre machine

Etapes

  1. Cloner le code source dans votre répertoire de travail

  2. Définir les variables d’environnement

    • Créez une copie de .env.exemple nommée .env

      Vous pouvez y définir vos propres valeurs, bien sûr, à condition qu’elles soient cohérentes avec le reste de la configuration. Notamment la valeur DOMAIN_NAME

  3. Lier votre DOMAIN_NAME au localhost :

    • Ajoutez ces deux lignes au fichier hosts : C:\Windows\System32\drivers\etc\hosts (sous Windows) et /etc/hosts (sous Linux).

      127.0.0.1 <nom-domaine-local>
      127.0.0.1 <prefixe-dashboard>.<nom-domaine-local>
      • Par exemple :
      127.0.0.1 mon-domaine-local.com
      127.0.0.1 mon-prefixe-dashboard.mon-domaine-local.com
  4. Créer le réseau commun (externe) utilisé par tous les services gérés par Traefik:

    • Ouvrez un terminal et tapez :
       docker network create my-external-network
  5. Lancer les services avec docker compose :

    • Dans votre terminal, placez-vous dans votre répertoire de travail et exécutez :
      docker compose -f docker-compose.yaml -f docker-compose.local.yaml up

Tests

  • Vérifiez que les conteneurs traefik-reverse-proxy et traefik-mkcert sont en cours d’exécution et en bonne santé.

  • Vérifiez votre dossier certs : s’il s’est doté de certificats locaux, c’est que tout s’est bien passé.

  • Dans les logs (ici via Docker Desktop), vous devriez voir ceci :

    Docker Desktop mkcert logs

  • Ouvrez l’adresse suivante dans votre navigateur : http://localhost:8080/dashboard/
    Vous devriez voir le tableau de bord suivant :

    Traefik Dashboard


Déploiement sur un Domaine Réel

Prérequis :

  • Accès SSH à un serveur de déploiement/hébergement
  • Un nom de domaine enregistré
  • Docker et Docker Compose installés sur le serveur

Configuration

À partir de maintenant, toutes les commandes/instructions supposent que vous êtes connecté à votre serveur distant via SSH.

  • Optionnel : Sécurisez l’accès au tableau de bord via une authentification BasicAuth (vous devez avoir htpasswd installé)

    • Générer les TRAEFIK_CREDENTIALS
      echo $(htpasswd -nb <votre-nom-utilisateur> <votre-mot-de-passe>) | sed -e s/\\$/\\$\\$/g
      • Notez les valeurs utilisées pour <votre-nom-utilisateur> et <votre-mot-de-passe>, elles seront nécessaires pour accéder au tableau de bord.
  1. Cloner (ou copier à distance) le code source dans le répertoire de travail de votre choix sur votre serveur

  2. Définir les variables d’environnement :

    • Créez une copie de .env.exemple nommée .env et remplissez-la avec :
      • ENV=prod
      • Votre propre DOMAIN_NAME
      • Votre propre DASHBOARD_PREFIX
      • Le cas échéant, la valeur générée pour TRAEFIK_CREDENTIALS
  3. Créer le réseau commun (externe) utilisé par tous les services gérés par Traefik :

    • Dans votre terminal ssh entrez :
      docker network create my-external-network
  4. Définir votre adresse e-mail de contact :

    ## docker-compose.prod.yaml ##
    64    ##############################################################################################
    65    # tlschallenge challenge
    66    ##############################################################################################
    67    # Email address used for registration.
    68    #
    69    # Required
    70    #
    71    #- "--certificatesresolvers.tlsResolver.acme.email=/secrets/cert_contact_email"
    72    - "--certificatesresolvers.tlsResolver.acme.email=contact@my-domain.com"

    Cette adresse doit être réelle, même en environnement de test (staging).

  5. Définir le serveur de certificats TLS :

    Utilisez le serveur staging de Let’s Encrypt pour éviter de dépasser la limite de requêtes lors des tests.

    ## docker-compose.prod.yaml ##
    80  # CA server to use.
    81  # Uncomment the line to use Let's Encrypt's staging server,
    82  # leave commented to go to prod.
    83  #
    84  # Optional
    85  # Default: "https://acme-v02.api.letsencrypt.org/directory"
    86  # Staging: "https://acme-staging-v02.api.letsencrypt.org/directory"
    87  #
    88  - "--certificatesresolvers.tlsResolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
  6. Préparer le sous-domaine du tableau de bord Traefik ::

    • Dans la zone DNS de votre fournisseur de domaine, ajoutez une entrée CNAME pour le tableau de bord. Exemple : si votre domaine est “mon-domaine.com” et que le DASHBOARD_PREFIX est “mon-dashboard-traefik”, vous devez créer “mon-dashboard-traefik.mon-domaine.com” en tant que CNAME pointant vers “mon-domaine.com
  7. Lancer Traefik en production :

    • Dans votre terminal, d’abord placez-vous sur votre répertoire de travail ensuite tapez :
      docker compose -f docker-compose.yaml -f docker-compose.prod.yaml up

Important!

Les certificats émis par les serveurs staging sont techniquement valides mais ne sont pas reconnus comme fiables par les navigateurs. Vous devrez ignorer l’avertissement NET::ERR_CERT_AUTHORITY_INVALID afin de les utiliser.


Tests

  • Vérifiez que le conteneur traefik-reverse-proxy fonctionne correctement.

  • Accédez au tableau de bord à : https://mon-dashboard-traefik.mon-domaine.com/dashboard/ (remplacez bien sûr par votre adresse réelle)

    Si vous avez configuré le BasicAuth, authentifiez-vous avec les username/password que vous aviez configuré précédemment

  • Vérifiez le fichier acme.json :

    • connectez-vous en ssh à votre serveur afin d’accéder au conteneur de votre reverse proxy :
    docker exec -it prod-traefik-reverse-proxy sh
    • Si vous ouvrez à présent votre fichier acme.json il devrait contenir les certificats pour le domaine principal et pour le(s) sous-domaine :
    cat /letsencrypt/acme.json

Analyse supplémentaire

  • Ici nous mettons simplement en place une redirection de toutes les requêtes http (port 80) vers https (port 443) :

    ## docker-compose.local.yaml ##
    11- "--entryPoints.web.address=:80"
    12- "--entryPoints.web.http.redirections.entryPoint.to=websecure"
    13- "--entryPoints.web.http.redirections.entryPoint.scheme=https"
    14- "--entryPoints.websecure.address=:443"

    En particulier dans la config de la prod, on met le https comme point d’entrée par default, anisi que la configuration du provider TLS certResolver :

    ## docker-compose.prod.yaml ##
    23  - "--entryPoints.web.address=:80"
    24  - "--entryPoints.web.http.redirections.entryPoint.to=websecure"
    25  - "--entryPoints.web.http.redirections.entryPoint.scheme=https"
    26  - "--entryPoints.websecure.address=:443"
    27  - "--entrypoints.websecure.asDefault=true"
    28  - "--entrypoints.websecure.http.tls.certResolver=tlsResolver"
  • En local, la génération de certificats TLS est gérée par un service tiers mkcert, ici:

    ## docker-compose.local.yaml ##
    38traefik-mkcert:
    39    image: vishnunair/docker-mkcert
    40    container_name: traefik-mkcert
    41
    42    environment:
    43    - domain=${DOMAIN_NAME}, *.${DOMAIN_NAME}
    44    volumes:
    45        - ./certs/:/root/.local/share/mkcert
    46    labels:
    47    - "traefik.enable=false"
    48    networks:
    49    - my-external-network

    Vous pouvez retrouver le repo du projet que j’ai emprunté ici : vishnunair/docker-mkcert

    Par ailleurs, étant donné que les deux conteneurs traefik-reverse-proxy et traefik-mkcert définissent un volume associé au répertoire “certs” de l’ordinateur hôte (host), le conteneur traefik-reverse-proxy peut donc lire les certificats générés par traefik-mkcert :

    ## docker-compose.local.yaml ##
    traefik-reverse-proxy:
        ...
        ...
        volumes:
            - ./certs/:/etc/certs:ro
        ...
        ...
    
    traefik-mkcert:
        ...
        ...
        volumes:
            - ./certs/:/root/.local/share/mkcert
        ...
        ...
  • En local, on définit un port supplémentaire 8080 :

    ## docker-compose.local.yaml ##
    33    ports:
    34    - "80:80"
    35    - "443:443"
    36    - "8080:8080"

    Sa config étant dehors celle des entryPoints, cela nous permet d’accéder facilement au dashboard Traefik, directement en http :

    ## docker-compose.local.yaml ##
    5    command:
    6    - "--api.dashboard=true"
    7    - "--api.insecure=true"
    8
    9    - "--serversTransport.insecureSkipVerify=true"
  • Coté prod, il arrive que le ficher acme.json aie des soucis de permissions si on le laisse tel quel, c’est pour cela que l’on définit explicitement ses permissions lors du runtime via :

    ## entrypoint.sh ##
    1#! /bin/sh
    2set -e
    3
    4echo "Setting acme.json permissions 0600"
    5touch /letsencrypt/acme.json
    6chmod 600 /letsencrypt/acme.json
    7chown root:root /letsencrypt
    8chown root:root /letsencrypt/acme.json

Conclusion

Nous avons mis en place un reverse proxy Traefik prêt à l’emploi avec génération automatique de certificats Let’s Encrypt, fonctionnant à la fois en local et sur un nom de domaine réel.

Prochaine étape : ajouter un service (conteneur Docker) ayant le même réseau externe que le notre actuel proxy, et observer la magie opérer — Traefik le détectera et le gérera automatiquement.