Comment utiliser Traefik v2 comme proxy inverse pour les conteneurs Docker sur Ubuntu 20.04

De Get Docs
Aller à :navigation, rechercher

L'auteur a sélectionné Girls Who Code pour recevoir un don dans le cadre du programme Write for DOnations.

Introduction

Docker peut être un moyen efficace d'exécuter des applications Web en production, mais vous souhaiterez peut-être exécuter plusieurs applications sur le même hôte Docker. Dans cette situation, vous devrez configurer un proxy inverse. En effet, vous souhaitez uniquement exposer les ports 80 et 443 au reste du monde.

Traefik est un proxy inverse compatible Docker qui comprend un tableau de bord de surveillance. Traefik v1 est largement utilisé depuis un certain temps, et vous pouvez suivre ce tutoriel précédent pour installer Traefik v1 ). Mais dans ce tutoriel, vous allez installer et configurer Traefik v2, qui comprend pas mal de différences.

La plus grande différence entre Traefik v1 et v2 est que frontends et backends ont été supprimés et leurs fonctionnalités combinées réparties sur routeurs, middlewares, et services. Auparavant, un backend se chargeait d'apporter des modifications aux requêtes et de transmettre cette requête à tout ce qui était censé la gérer. Traefik v2 offre une plus grande séparation des préoccupations en introduisant des middlewares qui peuvent modifier les requêtes avant de les envoyer à un service. Les middlewares facilitent la spécification d'une seule étape de modification qui peut être utilisée par de nombreuses routes différentes afin qu'elles puissent être réutilisées (comme HTTP Basic Auth, que vous verrez plus tard). Un routeur peut également utiliser de nombreux intergiciels différents.

Dans ce didacticiel, vous allez configurer Traefik v2 pour acheminer les requêtes vers deux conteneurs d'applications Web différents : un conteneur Wordpress et un conteneur Adminer, chacun parlant à un MySQL. base de données. Vous allez configurer Traefik pour qu'il serve tout sur HTTPS en utilisant Let's Encrypt.

Conditions préalables

Pour terminer ce tutoriel, vous aurez besoin des éléments suivants :

Étape 1 - Configuration et exécution de Traefik

Le projet Traefik a une image Docker officielle, vous l'utiliserez donc pour exécuter Traefik dans un conteneur Docker.

Mais avant de mettre votre conteneur Traefik en service, vous devez créer un fichier de configuration et configurer un mot de passe crypté pour pouvoir accéder au tableau de bord de surveillance.

Vous utiliserez l'utilitaire htpasswd pour créer ce mot de passe crypté. Tout d'abord, installez l'utilitaire, qui est inclus dans le package apache2-utils :

sudo apt-get install apache2-utils

Générez ensuite le mot de passe avec htpasswd. Remplacez secure_password par le mot de passe que vous souhaitez utiliser pour l'utilisateur administrateur Traefik :

htpasswd -nb admin secure_password

La sortie du programme ressemblera à ceci :

Outputadmin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/

Vous utiliserez cette sortie dans le fichier de configuration Traefik pour configurer l'authentification de base HTTP pour le tableau de bord de vérification et de surveillance de l'état Traefik. Copiez toute la ligne de sortie afin de pouvoir la coller plus tard.

Pour configurer le serveur Traefik, vous allez créer deux nouveaux fichiers de configuration appelés traefik.toml et traefik_dynamic.toml en utilisant le format TOML. TOML est un langage de configuration similaire aux fichiers INI, mais standardisé. Ces fichiers nous permettent de configurer le serveur Traefik et diverses intégrations, ou providers, que vous souhaitez utiliser. Dans ce didacticiel, vous utiliserez trois des fournisseurs disponibles de Traefik : api, docker et acme. Le dernier d'entre eux, acme, prend en charge les certificats TLS à l'aide de Let's Encrypt.

Créez et ouvrez traefik.toml à l'aide de nano ou de votre éditeur de texte préféré :

nano traefik.toml

Tout d'abord, vous souhaitez spécifier les ports sur lesquels Traefik doit écouter à l'aide de la section entryPoints de votre fichier de configuration. Vous en voulez deux parce que vous voulez écouter sur les ports 80 et 443. Appelons-les web (port 80) et websecure (port 443).

Ajoutez les configurations suivantes :

traefik.toml

[entryPoints]
  [entryPoints.web]
    address = ":80"
    [entryPoints.web.http.redirections.entryPoint]
      to = "websecure"
      scheme = "https"

  [entryPoints.websecure]
    address = ":443"

Notez que vous redirigez également automatiquement le trafic à gérer via TLS.

Ensuite, configurez le Traefik api, qui vous donne accès à la fois à l'API et à l'interface de votre tableau de bord. La rubrique [api] est tout ce dont vous avez besoin car le tableau de bord est alors activé par défaut, mais vous serez explicite pour le moment.

Ajoutez le code suivant :

traefik.toml

...
[api]
  dashboard = true

Pour terminer la sécurisation de vos requêtes Web, vous souhaitez utiliser Let's Encrypt pour générer des certificats TLS valides. Traefik v2 prend en charge Let's Encrypt prêt à l'emploi et vous pouvez le configurer en créant un résolveur de certificats du type acme.

Configurons maintenant votre résolveur de certificats en utilisant le nom lets-encrypt :

traefik.toml

...
[certificatesResolvers.lets-encrypt.acme]
  email = "[email protected]_domain"
  storage = "acme.json"
  [certificatesResolvers.lets-encrypt.acme.tlsChallenge]

Cette section s'appelle acme car ACME est le nom du protocole utilisé pour communiquer avec Let's Encrypt pour gérer les certificats. Le service Let's Encrypt nécessite une inscription avec une adresse e-mail valide, donc pour que Traefik génère des certificats pour vos hôtes, définissez la clé email sur votre adresse e-mail. Vous spécifiez ensuite que vous stockerez les informations que vous recevrez de Let's Encrypt dans un fichier JSON appelé acme.json.

La section acme.tlsChallenge nous permet de spécifier comment Let's Encrypt peut vérifier que le certificat. Vous le configurez pour servir un fichier dans le cadre du challenge sur le port 443.

Enfin, vous devez configurer Traefik pour qu'il fonctionne avec Docker.

Ajoutez les configurations suivantes :

traefik.toml

...
[providers.docker]
  watch = true
  network = "web"

Le fournisseur docker permet à Traefik d'agir en tant que proxy devant les conteneurs Docker. Vous avez configuré le fournisseur sur watch pour les nouveaux conteneurs sur le réseau web, que vous créerez bientôt.

Notre configuration finale utilise le fournisseur file. Avec Traefik v2, les configurations statiques et dynamiques ne peuvent pas être mélangées et assorties. Pour contourner cela, vous utiliserez traefik.toml pour définir vos configurations statiques puis conserverez vos configurations dynamiques dans un autre fichier, que vous appellerez traefik_dynamic.toml. Ici, vous utilisez le fournisseur file pour indiquer à Traefik qu'il doit lire dans des configurations dynamiques à partir d'un fichier différent.

Ajoutez le fournisseur file suivant :

traefik.toml

[providers.file]
  filename = "traefik_dynamic.toml"

Votre traefik.toml terminé ressemblera à ceci :

traefik.toml

[entryPoints]
  [entryPoints.web]
    address = ":80"
    [entryPoints.web.http.redirections.entryPoint]
      to = "websecure"
      scheme = "https"

  [entryPoints.websecure]
    address = ":443"

[api]
  dashboard = true

[certificatesResolvers.lets-encrypt.acme]
  email = "[email protected]_domain"
  storage = "acme.json"
  [certificatesResolvers.lets-encrypt.acme.tlsChallenge]

[providers.docker]
  watch = true
  network = "web"

[providers.file]
  filename = "traefik_dynamic.toml"

Enregistrez et fermez le fichier.

Créons maintenant traefik_dynamic.toml.

Les valeurs de configuration dynamiques que vous devez conserver dans leur propre fichier sont les middlewares et les routeurs. Pour placer votre tableau de bord derrière un mot de passe, vous devez personnaliser le routeur de l'API et configurer un middleware pour gérer l'authentification de base HTTP. Commençons par configurer le middleware.

Le middleware est configuré sur une base par protocole et puisque vous travaillez avec HTTP, vous le spécifierez comme une section enchaînée de http.middlewares. Vient ensuite le nom de votre middleware afin que vous puissiez le référencer ultérieurement, suivi du type de middleware dont il s'agit, qui sera basicAuth dans ce cas. Appelons votre middleware simpleAuth.

Créez et ouvrez un nouveau fichier nommé traefik_dynamic.toml :

nano traefik_dynamic.toml

Ajoutez le code suivant. C'est ici que vous collerez la sortie de la commande htpasswd :

traefik_dynamic.toml

[http.middlewares.simpleAuth.basicAuth]
  users = [
    "admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/"
  ]

Pour configurer le routeur pour l'API, vous enchaînerez à nouveau le nom du protocole, mais au lieu d'utiliser http.middlewares, vous utiliserez http.routers suivi du nom du routeur. Dans ce cas, le api fournit son propre routeur nommé que vous pouvez configurer à l'aide de la section [http.routers.api]. Vous configurerez également le domaine que vous prévoyez d'utiliser avec votre tableau de bord en définissant la clé rule à l'aide d'une correspondance d'hôte, le point d'entrée à utiliser websecure et les middlewares à inclure [ X193X].

Ajoutez les configurations suivantes :

traefik_dynamic.toml

...
[http.routers.api]
  rule = "Host(`monitor.your_domain`)"
  entrypoints = ["websecure"]
  middlewares = ["simpleAuth"]
  service = "[email protected]"
  [http.routers.api.tls]
    certResolver = "lets-encrypt"

Le point d'entrée web gère le port 80, tandis que le point d'entrée websecure utilise le port 443 pour TLS/SSL. Vous redirigez automatiquement tout le trafic sur le port 80 vers le point d'entrée websecure pour forcer des connexions sécurisées pour toutes les requêtes.

Notez que les trois dernières lignes ici configurent un service, activent tls et configurent certResolver sur "lets-encrypt". Les services sont la dernière étape pour déterminer où une demande est finalement traitée. Le service [email protected] est un service intégré qui se trouve derrière l'API que vous exposez. Tout comme les routeurs et les middlewares, les services peuvent être configurés dans ce fichier, mais vous n'aurez pas besoin de le faire pour obtenir le résultat souhaité.

Votre fichier traefik_dynamic.toml terminé ressemblera à ceci :

traefik_dynamic.toml

[http.middlewares.simpleAuth.basicAuth]
  users = [
    "admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/"
  ]

[http.routers.api]
  rule = "Host(`monitor.your_domain`)"
  entrypoints = ["websecure"]
  middlewares = ["simpleAuth"]
  service = "[email protected]"
  [http.routers.api.tls]
    certResolver = "lets-encrypt"

Enregistrez le fichier et quittez l'éditeur.

Avec ces configurations en place, vous allez maintenant démarrer Traefik.

Étape 2 - Exécution du conteneur Traefik

Dans cette étape, vous allez créer un réseau Docker que le proxy partagera avec les conteneurs. Vous accéderez alors au tableau de bord Traefik. Le réseau Docker est nécessaire pour que vous puissiez l'utiliser avec des applications exécutées à l'aide de Docker Compose.

Créez un nouveau réseau Docker appelé web :

docker network create web

Lorsque le conteneur Traefik démarrera, vous l'ajouterez à ce réseau. Ensuite, vous pouvez ajouter ultérieurement des conteneurs supplémentaires à ce réseau pour que Traefik puisse être mandaté.

Ensuite, créez un fichier vide qui contiendra vos informations Let's Encrypt. Vous partagerez ceci dans le conteneur afin que Traefik puisse l'utiliser :

touch acme.json

Traefik ne pourra utiliser ce fichier que si l'utilisateur root à l'intérieur du conteneur dispose d'un accès unique en lecture et en écriture. Pour ce faire, verrouillez les autorisations sur acme.json afin que seul le propriétaire du fichier dispose des autorisations de lecture et d'écriture.

chmod 600 acme.json

Une fois le fichier transmis à Docker, le propriétaire passera automatiquement à l'utilisateur root à l'intérieur du conteneur.

Enfin, créez le conteneur Traefik avec cette commande :

docker run -d \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v $PWD/traefik.toml:/traefik.toml \
  -v $PWD/traefik_dynamic.toml:/traefik_dynamic.toml \
  -v $PWD/acme.json:/acme.json \
  -p 80:80 \
  -p 443:443 \
  --network web \
  --name traefik \
  traefik:v2.2

Cette commande est un peu longue. Décomposons-le.

Vous utilisez l'indicateur -d pour exécuter le conteneur en arrière-plan en tant que démon. Vous partagez ensuite votre fichier docker.sock dans le conteneur afin que le processus Traefik puisse écouter les modifications apportées aux conteneurs. Vous partagez également les fichiers de configuration traefik.toml et traefik_dynamic.toml dans le conteneur, ainsi que acme.json.

Ensuite, vous mappez les ports :80 et :443 de votre hôte Docker aux mêmes ports dans le conteneur Traefik afin que Traefik reçoive tout le trafic HTTP et HTTPS vers le serveur.

Vous définissez le réseau du conteneur sur web et vous nommez le conteneur traefik.

Enfin, vous utilisez l'image traefik:v2.2 pour ce conteneur afin de garantir que vous n'exécutez pas une version complètement différente de celle pour laquelle ce didacticiel est écrit.

L'ENTRYPOINT d'une image Docker est une commande qui s'exécute toujours lorsqu'un conteneur est créé à partir de l'image. Dans ce cas, la commande est le binaire traefik dans le conteneur. Vous pouvez transmettre des arguments supplémentaires à cette commande lorsque vous lancez le conteneur, mais vous avez configuré tous vos paramètres dans le fichier traefik.toml.

Une fois le conteneur démarré, vous disposez maintenant d'un tableau de bord auquel vous pouvez accéder pour voir la santé de vos conteneurs. Vous pouvez également utiliser ce tableau de bord pour visualiser les routeurs, les services et les middlewares que Traefik a enregistrés. Vous pouvez essayer d'accéder au tableau de bord de surveillance en pointant votre navigateur vers https://monitor.your_domain/dashboard/ (le / final est requis).

Vous serez invité à entrer votre nom d'utilisateur et votre mot de passe, qui sont admin et le mot de passe que vous avez configuré à l'étape 1.

Une fois connecté, vous verrez l'interface Traefik :

Vous remarquerez qu'il existe déjà des routeurs et des services enregistrés, mais ce sont ceux qui sont fournis avec Traefik et la configuration du routeur que vous avez écrite pour l'API.

Votre proxy Traefik est maintenant en cours d'exécution et vous l'avez configuré pour fonctionner avec Docker et surveiller d'autres conteneurs. À l'étape suivante, vous démarrerez certains conteneurs pour que Traefik utilise le proxy.

Étape 3 - Enregistrement des conteneurs avec Traefik

Avec le conteneur Traefik en cours d'exécution, vous êtes prêt à exécuter des applications derrière lui. Lançons les conteneurs suivants derrière Traefik :

  1. Un blog utilisant l'image WordPress officielle.
  2. Un serveur de gestion de base de données utilisant l'image Adminer officielle.

Vous gérerez ces deux applications avec Docker Compose à l'aide d'un fichier docker-compose.yml.

Créez et ouvrez le fichier docker-compose.yml dans votre éditeur :

nano docker-compose.yml

Ajoutez les lignes suivantes au fichier pour spécifier la version et les réseaux que vous utiliserez :

docker-compose.yml

version: "3"

networks:
  web:
    external: true
  internal:
    external: false

Vous utilisez Docker Compose version 3 car il s'agit de la dernière version majeure du format de fichier Compose.

Pour que Traefik reconnaisse vos applications, elles doivent faire partie du même réseau, et puisque vous avez créé le réseau manuellement, vous l'intégrez en spécifiant le nom de réseau de web et en définissant external sur [ X211X]. Ensuite, vous définissez un autre réseau afin de pouvoir connecter vos conteneurs exposés à un conteneur de base de données que vous n'exposerez pas via Traefik. Vous appellerez ce réseau internal.

Ensuite, vous définirez chacun de vos services, un à la fois. Commençons par le conteneur blog, que vous baserez sur l'image officielle de WordPress. Ajoutez cette configuration au bas du fichier :

docker-compose.yml

...

services:
  blog:
    image: wordpress:4.9.8-apache
    environment:
      WORDPRESS_DB_PASSWORD:
    labels:
      - traefik.http.routers.blog.rule=Host(`blog.your_domain`)
      - traefik.http.routers.blog.tls=true
      - traefik.http.routers.blog.tls.certresolver=lets-encrypt
      - traefik.port=80
    networks:
      - internal
      - web
    depends_on:
      - mysql

La clé environment vous permet de spécifier les variables d'environnement qui seront définies à l'intérieur du conteneur. En ne définissant pas de valeur pour WORDPRESS_DB_PASSWORD, vous dites à Docker Compose d'obtenir la valeur de votre shell et de la transmettre lorsque vous créez le conteneur. Vous définirez cette variable d'environnement dans votre shell avant de démarrer les conteneurs. De cette façon, vous ne codez pas les mots de passe en dur dans le fichier de configuration.

La section labels est l'endroit où vous spécifiez les valeurs de configuration pour Traefik. Les étiquettes Docker ne font rien par elles-mêmes, mais Traefik les lit pour savoir comment traiter les conteneurs. Voici ce que fait chacune de ces étiquettes :

  • traefik.http.routers.adminer.rule=Host(``` blog.your_domain ```) creates a new routeur for your container and then specifies the routing rule used to determine if a request matches this container.
  • traefik.routers.custom_name.tls=true spécifie que ce routeur doit utiliser TLS.
  • traefik.routers.custom_name.tls.certResolver=lets-encrypt spécifie que le résolveur de certificats que vous avez créé précédemment appelé lets-encrypt doit être utilisé pour obtenir un certificat pour cette route.
  • traefik.port spécifie le port exposé que Traefik doit utiliser pour acheminer le trafic vers ce conteneur.

Avec cette configuration, tout le trafic envoyé à votre hôte Docker sur le port 80 ou 443 avec le domaine de blog.your_domain sera acheminé vers le conteneur blog.

Vous affectez ce conteneur à deux réseaux différents afin que Traefik puisse le trouver via le réseau web et qu'il puisse communiquer avec le conteneur de base de données via le réseau internal.

Enfin, la clé depends_on indique à Docker Compose que ce conteneur doit démarrer après que ses dépendances sont en cours d'exécution. Étant donné que WordPress a besoin d'une base de données pour fonctionner, vous devez exécuter votre conteneur mysql avant de démarrer votre conteneur blog.

Ensuite, configurez le service MySQL :

docker-compose.yml

services:
...
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD:
    networks:
      - internal
    labels:
      - traefik.enable=false

Vous utilisez l'image officielle MySQL 5.7 pour ce conteneur. Vous remarquerez que vous utilisez à nouveau un élément environment sans valeur. Les variables MYSQL_ROOT_PASSWORD et WORDPRESS_DB_PASSWORD devront être définies sur la même valeur pour s'assurer que votre conteneur WordPress peut communiquer avec MySQL. Vous ne voulez pas exposer le conteneur mysql à Traefik ou au monde extérieur, vous n'attribuez donc ce conteneur qu'au réseau internal. Étant donné que Traefik a accès au socket Docker, le processus exposera toujours un routeur pour le conteneur mysql par défaut, vous ajouterez donc l'étiquette traefik.enable=false pour spécifier que Traefik ne doit pas exposer ce conteneur .

Enfin, définissez le conteneur Adminer :

docker-compose.yml

services:
...
  adminer:
    image: adminer:4.6.3-standalone
    labels:
      - traefik.http.routers.adminer.rule=Host(`db-admin.your_domain`)
      - traefik.http.routers.adminer.tls=true
      - traefik.http.routers.adminer.tls.certresolver=lets-encrypt
      - traefik.port=8080
    networks:
      - internal
      - web
    depends_on:
      - mysql

Ce conteneur est basé sur l'image officielle d'Adminer. La configuration network et depends_on pour ce conteneur correspond exactement à ce que vous utilisez pour le conteneur blog.

La ligne traefik.http.routers.adminer.rule=Host(``` db-admin.your_domain ```) indique à Traefik d'examiner l'hôte demandé. S'il correspond au modèle de db-admin.your_domain, Traefik acheminera le trafic vers le conteneur adminer via le port 8080.

Votre fichier docker-compose.yml terminé ressemblera à ceci :

docker-compose.yml

version: "3"

networks:
  web:
    external: true
  internal:
    external: false

services:
  blog:
    image: wordpress:4.9.8-apache
    environment:
      WORDPRESS_DB_PASSWORD:
    labels:
      - traefik.http.routers.blog.rule=Host(`blog.your_domain`)
      - traefik.http.routers.blog.tls=true
      - traefik.http.routers.blog.tls.certresolver=lets-encrypt
      - traefik.port=80
    networks:
      - internal
      - web
    depends_on:
      - mysql

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD:
    networks:
      - internal
    labels:
      - traefik.enable=false

  adminer:
    image: adminer:4.6.3-standalone
    labels:
    labels:
      - traefik.http.routers.adminer.rule=Host(`db-admin.your_domain`)
      - traefik.http.routers.adminer.tls=true
      - traefik.http.routers.adminer.tls.certresolver=lets-encrypt
      - traefik.port=8080
    networks:
      - internal
      - web
    depends_on:
      - mysql

Enregistrez le fichier et quittez l'éditeur de texte.

Ensuite, définissez les valeurs dans votre shell pour les variables WORDPRESS_DB_PASSWORD et MYSQL_ROOT_PASSWORD :

export WORDPRESS_DB_PASSWORD=secure_database_password
export MYSQL_ROOT_PASSWORD=secure_database_password

Remplacez secure_database_password par le mot de passe de votre base de données. N'oubliez pas d'utiliser le même mot de passe pour WORDPRESS_DB_PASSWORD et MYSQL_ROOT_PASSWORD.

Une fois ces variables définies, exécutez les conteneurs à l'aide de docker-compose :

docker-compose up -d

Regardez maintenant le tableau de bord d'administration Traefik pendant qu'il se remplit.

Si vous explorez la section Routeurs, vous trouverez des routeurs pour adminer et blog configurés avec TLS :

Accédez à blog.your_domain, en remplaçant your_domain par votre domaine. Vous serez redirigé vers une connexion TLS et vous pourrez maintenant terminer la configuration de WordPress :

Accédez maintenant à Adminer en visitant db-admin.your_domain dans votre navigateur, en remplaçant à nouveau your_domain par votre domaine. Le conteneur mysql n'est pas exposé au monde extérieur, mais le conteneur adminer y a accès via le réseau Docker internal qu'ils partagent à l'aide du mysql. ] nom du conteneur en tant que nom d'hôte.

Sur l'écran de connexion Adminer, entrez root pour Nom d'utilisateur, entrez mysql pour Serveur, et entrez la valeur que vous avez définie pour [X141X ] pour le Mot de passe. Laissez Database vide. Appuyez maintenant sur Connexion.

Une fois connecté, vous verrez l'interface utilisateur Adminer.

Les deux sites fonctionnent maintenant et vous pouvez utiliser le tableau de bord sur monitor.your_domain pour garder un œil sur vos applications.

Conclusion

Dans ce didacticiel, vous avez configuré Traefik v2 pour envoyer des requêtes proxy à d'autres applications dans des conteneurs Docker.

La configuration déclarative de Traefik au niveau du conteneur d'applications facilite la configuration de plus de services, et il n'est pas nécessaire de redémarrer le conteneur traefik lorsque vous ajoutez de nouvelles applications au trafic proxy puisque Traefik remarque les changements immédiatement via le fichier socket Docker c'est de la surveillance.

Pour en savoir plus sur ce que vous pouvez faire avec Traefik v2, rendez-vous sur la documentation officielle de Traefik.