Traefik v2 HTTPS (SSL) en localhost

Souhaitant pouvoir bénéficier d’un reverse-proxy avec support du SSL lors de mes développements (donc sur une machine en local), je me suis heurté à quelques petites difficultés sur la configuration de Traefik. On trouve en effet, facilement des ressources pour la première version de Traefik, mais depuis les 26 août, Traefik est passé en 2.X.X. Ainsi, les configurations de la 1.X.X ne sont plus entièrement applicables pour cette nouvelle version.

Ce billet a pour but de te fournir une configuration minimale te permettant de pouvoir bénéficier du SSL en local avec Traefik, en utilisant Docker.

TL;DR :

Un petit projet minimal est disponnible sur mon GitHub.

Un certificat auto-signé

Pour avoir dur SSL en localhost, il n’est pas possible d’utiliser let’s encrypt. Il faudra passer par un certificat auto-signé. Pour faciliter tout cela, tu peux utiliser mkcert, un utilitaire permettant de créer des certificats auto-signés pour ses domaines et de les approuver pour ne pas avoir le vilain message des navigateurs.

Une fois installé, il faut exécuter la commande suivante pour créer une autorité de confiance local, qui nous servira pour signer nos certificats :

mkcert -install

Maintenant, imaginons que nous souhaitons avoir des certificats pour docker.localhost et domain.local (et leurs sous-domaines), nous pouvons généré un des certificats signé avec notre autorité de confiance local ainsi :

# On créer un répertoire qui va contenir nos certificats
mkdir certs

# Puis on créer les certificats
mkcert -cert-file certs/local-cert.pem -key-file certs/local-key.pem "docker.localhost" "*.docker.localhost" "domain.local" "*.domain.local"

Note : pour les certificats wildcards (des sous-domaines), il ne support que le niveau de wildcard que l’on met. Autrement dit, si je prends par exemple *.docker.localhost, le certificat fonctionnera pour foo.docker.localhost, bar.docker.localhost, etc. mais pas pour foo.bar.docker.localhost.

Nous avons maintenant des certificats prêts à l’emploi pour notre dev.

Configuration de Traefik

À présent, passons à la configuration de Traefik. Ici rien de bien compliquer, il suffit de bien lire la doc. Pour t’éviter trop de lecture, voici un résumé.

Traefik 2 fonctionne avec un système de configuration statique et dynamique. La configuration statique est chargée au démarrage, et tout changement dans cette configuration nécessitera un redémarrage de Traefik. La configuration dynamique quant à elle permet d’être changé à chaud.

Configuration statiquie et dynamique
Configuration statiquie et dynamique

Source de l’image.

Qu’est-ce qui change par rapport à la V1 ?

Dans le guide de migration il est dit que la configuration du SSL est déplacée de l'entrypoint au router.

Voici la configuration statique :

# traefik/traefik.yml
global:
  sendAnonymousUsage: false

api:
  dashboard: true
  insecure: true

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    watch: true
    exposedByDefault: false

  file:
    filename: /etc/traefik/config.yml
    watch: true

log:
  level: INFO
  format: common

entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
  https:
    address: ":443"

Comme on peut le constater, on force une redirection de HTTP sur HTTPS.

Au niveau de la configuration dynamique nous avons ceci :

# traefik/config.yml
http:
  routers:
    traefik:
      rule: "Host(`traefik.docker.localhost`)"
      service: "api@internal"
      tls:
        domains:
          - main: "docker.localhost"
            sans:
              - "*.docker.localhost"
          - main: "domain.local"
            sans:
              - "*.domain.local"

tls:
  certificates:
    - certFile: "/etc/certs/local-cert.pem"
      keyFile: "/etc/certs/local-key.pem"

Ici, on spécifie le certificat à utiliser pour le SSL, et on rajoute la configuration d’un router nommé "traefik". Cela évitera d’avoir à le faire dans le docker-compose.yml

Configuration des conteneurs avec docker-compose

Maintenant qu’on a des certificats auto-signés et qu’on a configuré Traefik, il est temps de s’attaquer à la configuration de nos conteneurs pour qu’ils puissent être accessible depuis Traefik.

Dans un premier temps, nous allons créer un réseau docker pour notre proxy:

docker network create proxy

Je me suis basé sur l’exemple de base de la doc de Traefik pour l’exemple :

# docker-compose.yml
version: '3'

services:
  reverse-proxy:
    image: traefik:v2.3
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      # Web
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      # On map la conf statique dans le conteneur
      - ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro
      # On map la conf dynamique statique dans le conteneur
      - ./traefik/config.yml:/etc/traefik/config.yml:ro
      # On map les certificats dans le conteneur
      - ./certs:/etc/certs:ro
    networks:
      - proxy
    labels:
      # Permettre à ce conteneur d'être accessible par traefik
      # Pour plus d'information, voir : https://docs.traefik.io/providers/docker/#exposedbydefault
      - "traefik.enable=true"
      # Utilise la configuration du routeur "traefik" définie dans le fichier de configuration dynamique : ./traefik/config.yml
      - "traefik.http.routers.traefik=true"

  whoami:
    image: containous/whoami
    container_name: whoami
    security_opt:
      - no-new-privileges:true
    labels:
      - "traefik.enable=true"
      # URL pour accéder à ce conteneur
      - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
      # Activation de TLS
      - "traefik.http.routers.whoami.tls=true"
      # Si le port est différent de 80, utilisez le service suivant:
      # - "traefik.http.services.<service_name>.loadbalancer.server.port=<port>"
    networks:
      - proxy

networks:
  proxy:
    external: true

Il suffit ensuite de démarrer nos conteneurs avec docker-compose -f docker-compose.yml up et le tour est joué !

Vous pouvez accéder au dashboard de Træfik via l’URL suivante : traefik.docker.localhost.

Et vous pouvez accéder à l’example (whoami) via l’URL suivante : whoami.docker.localhost


C’est tout pour ce billet. De ce simple exemple tu pourras ensuite y intégrer toute ta constellation de conteneurs sans trop de difficulté.

Et garder à l’esprit que vous pouvez également mapper du TCP et de l’UDP avec Træfik.

9 commentaires

Très bon article. J’apprécie de voir que tu utilises déjà traefik 2. Beaucoup de resources sur le net font encore largement référence à la version 1.x dont les labels ne sont plus du tout compatibles avec la v2.

Pour être tout à fait complet il manque encore la configuration du domain whoami.domain.local pour qu’il pointe sur ta machine.

Pour ma part je me suis aussi penché sur la création de containers accessibles en HTTP/2 (et donc à fortiori en https). Et pour répondre aux 2 problématiques (config certificats et config DNS), j’ai mis en place un petit service : https://traefik.me.

Vous trouverez un exemple de docker-compose complet ici : https://gist.github.com/pyrou/4f555cd55677331c742742ee6007a73a

Un tout petit conteneur s’occupe de télécharger les certificats et de les partager à traefik.

Plus besoin d’installation de certificat root CA, plus de config /etc/hosts, plus de generation de certificat.

Humm, quel est l’intéret d’avoir https en local ?

ache

Principalement pour du dev.

Quand tu developpe à la fois une api et son front par exemple qui s’échangent des données en http, tu as des libs front qui t’imposent une connexion en https. Ça m’est déjà arrivé avec axios par exemple.

Super article, cependant, petite erreur: Il se trouve que si un fichier de configuration .toml est fourni, les arguments du binaire traefik seront ignorés. Donc pour accéder à l’interface web, il suffit d’ajouter ceci dans votre conf:

[api]
  insecure = true

Super article, cependant, petite erreur: Il se trouve que si un fichier de configuration .toml est fourni, les arguments du binaire traefik seront ignorés. Donc pour accéder à l’interface web, il suffit d’ajouter ceci dans votre conf:

[api]
  insecure = true

gcanal

Tu m’a appris quelque chose :D C’est la même chose pour les fichiers de conf dans d’autres formats (je pense notamment au .yml)

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte