Introduction

Docker peut être un moyen efficace d'exécuter des applications Web en production, mais vous pouvez exécuter plusieurs applications sur le même hôte Docker. Dans ce cas, vous devrez configurer un proxy inverse notamment si vous ne souhaitez pas exposer les ports 80 et 443 au reste du monde.

Traefik est un proxy inverse compatible Docker et écrit en Go (décidemment ;) ) qui inclut son propre tableau de bord de surveillance. Dans ce didacticiel, vous allez utiliser Traefik pour router les demandes vers deux conteneurs d'applications Web différents: un conteneur Wordpress et un conteneur Adminer, chacun parlant à une base de données MySQL. Nous allons donc configurer Traefik avec de l'HTTPS en utilisant Let's Encrypt.

Pré-requis

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

  • Un serveur Ubuntu 16.04 configuré en suivant le guide de configuration initial du serveur Ubuntu 16.04 sur l'hébergeur que vous utilisez (OVH pour moi).
  • Un hôte Docker en cours d'exécution (sur le VPS utilisé, il en fournisse des tous faits chez OVH, sinon voir ici.
  • Docker Compose installé
  • Un domaine et trois enregistrements A, db-admin, blog et moniteur, qui pointent chacun vers l'adresse IP de votre hôte Docker (VPS). Tout au long de ce tutoriel, remplacez votre domaine par example.com dans les fichiers de configuration et les exemples. J'ai moi-même choisi le nom de domaine gabrielsagnard.fr hébergé chez OVH pour ce tuto'.

1_h9iJ9whjCQ-ovuSGOCOVcA

Let's go !

Étape 1 - Configuration et fonctionnement de Traefik

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

Mais avant que notre conteneur Traefik ne soit opérationnel, nous devons créer un fichier de configuration et configurer un mot de passe chiffré afin que nous puissions accéder au tableau de bord de surveillance.

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

sudo apt-get install apache2-utils`

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

htpasswd -nb admin securepassword

La réponse du programme ressemblera à ceci:

Réponse :

admin:$apr1$FYJNgYWT$NK.uLajgnX7sy8/LKC.Ot0

Vous utiliserez cette réponse dans le fichier de configuration de Traefik pour configurer l'authentification de base HTTP pour le tableau de bord de contrôle d'intégrité et de surveillance de Traefik. Copiez toute la ligne de réponse afin de pouvoir la coller plus tard.

Pour configurer le serveur Traefik, nous allons créer un nouveau fichier de configuration appelé traefik.toml en utilisant le format TOML. TOML est un langage de configuration similaire aux fichiers INI, mais il est standardisé. Ce fichier nous permet de configurer le serveur Traefik et diverses intégrations, ou fournisseurs, que nous voulons utiliser. Dans ce tutoriel, nous allons utiliser trois des fournisseurs disponibles de Traefik: web, docker, et acme, qui est utilisé pour supporter TLS en utilisant Let's Encrypt.

nano traefik.toml

Tout d'abord, ajoutez deux points d'entrée nommés, http et https, auxquels tous les backends auront accès par défaut:

traefik.toml
defaultEntryPoints = ["http", "https"]

Nous allons configurer les points d'entrée http et https plus tard dans ce fichier.

Ensuite, configurez le fournisseur Web, ce qui vous donne accès à une interface de tableau de bord. C'est ici que vous allez coller la sortie de la commande htpasswd:

traefik.toml
...
[web]
adresse = ": 8080"
[web.auth.basic]
users = ["admin: votre mot de passeencrypted"]

Le tableau de bord est une application Web distincte qui s'exécutera dans le conteneur Traefik. Nous avons défini le tableau de bord pour qu'il s'exécute sur le port 8080.

La section web.auth.basic configure l'authentification de base HTTP pour le tableau de bord. Utilisez la sortie de la commande htpasswd que vous venez de lancer pour la valeur de l'entrée des utilisateurs. Vous pouvez spécifier des connexions supplémentaires en les séparant par des virgules.

Ensuite, définissez les points d'entrée. La section entryPoints configure les adresses que Traefik et les conteneurs mandatés peuvent écouter. Ajoutez ces lignes au fichier:

traefik.toml
...
[points d'entrée]
  [entryPoints.http]
  adresse = ": 80"
    [entryPoints.http.redirect]
      entryPoint = "https"
  [entryPoints.https]
  adresse = ": 443"
    [entryPoints.https.tls]

Le point d'entrée http gère le port 80, tandis que le point d'entrée https utilise le port 443 pour TLS / SSL. Nous redirigeons automatiquement tout le trafic sur le port 80 vers le point d'entrée https pour forcer des connexions sécurisées pour toutes les demandes.

Enfin, ajoutez cette section pour configurer la prise en charge des certificats de Let's Encrypt pour Traefik:

traefik.toml
...
[acmé]
email = "youremail@example.com"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
onDemand = false

Cette section s'appelle acme car ACME est le nom du protocole utilisé pour communiquer avec Let's Encrypt afin de gérer les certificats. Pour que Traefik génère des certificats pour nos hôtes, nous définissons la clé de courrier électronique sur votre adresse e-mail. Nous spécifions ensuite que nous allons stocker les informations que nous allons recevoir de Let's Encrypt dans un fichier JSON appelé acme.json. La clé entryPoint doit pointer vers le port de gestion de point d'entrée 443, qui dans notre cas est le point d'entrée https.

Les deux dernières clés, onHostRule et onDemand, dictent la manière dont Traefik doit procéder pour générer des certificats. Nous voulons récupérer nos certificats dès que nos conteneurs avec des noms d'hôtes spécifiés sont créés, et c'est ce que le paramètre onHostRule fera. Le paramètre onDemand tente de générer des certificats la première fois qu'une demande est effectuée. Cela ralentirait la première demande et serait très perceptible pour le visiteur, donc nous éviterons cela.

Enregistrez le fichier et quittez l'éditeur. Avec toute cette configuration en place, nous pouvons lancer Traefik.

Étape 2 - Exécution du conteneur Traefik

Ensuite, créez un réseau Docker pour le proxy à partager avec les conteneurs. Le réseau Docker est nécessaire pour que nous puissions l'utiliser avec des applications exécutées à l'aide de Docker Compose. Appelons ce réseau "proxy".

docker network create proxy

Lorsque le conteneur Traefik démarre, nous l'ajoutons à ce réseau. Ensuite, nous pouvons ajouter des conteneurs supplémentaires à ce réseau plus tard pour Traefik à proxy.

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

touch acme.json

Puis verrouillez les autorisations sur ce fichier afin que seul l'utilisateur root puisse lire et écrire dans ce fichier. Si vous ne le faites pas, Traefik ne pourra pas démarrer.

chmod 600 acme.json

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 / acme.json: /acme.json \
  -p 80:80 \
  -p 443: 443 \
  -l traefik.frontend.rule = Hôte: monitor.example.com \
  -l traefik.port = 8080 \
  - proxy réseau \
  --name traefik \
  traefik: 1.3.6-alpine --docker

Capture-d-e-cran-2018-03-20-a--18.27.40

La commande est un peu longue, alors décomposons-la.

Nous utilisons l'option -d pour exécuter le conteneur en arrière-plan en tant que démon. Nous partageons ensuite notre fichier docker.sock dans le conteneur afin que le processus Traefik puisse écouter les modifications apportées aux conteneurs. Nous partageons également le fichier de configuration traefik.toml et le fichier acme.json que nous avons créé dans le conteneur.

Ensuite, nous mappons les ports: 80 et: 443 de notre 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.

Ensuite, nous avons mis en place deux labels Docker qui indiquent à Traefik de diriger le trafic vers le nom d'hôte monitor.example.com vers le port: 8080 dans le conteneur Traefik, exposant ainsi le tableau de bord de surveillance.

Nous définissons le réseau du conteneur à proxy, et nous nommons le conteneur traefik.

Enfin, nous utilisons l'image traefik: 1.3.6-alpine pour ce conteneur, car il est petit.

alpine-traefik

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 passer des arguments supplémentaires à cette commande lorsque vous lancez le conteneur. Dans notre cas, nous passons l'argument --docker à l'ENTRYPOINT qui garantit que le fournisseur docker est enregistré avec les paramètres par défaut. Le fournisseur docker permet à Traefik d'agir en tant que proxy devant les conteneurs Docker. La configuration par défaut du fournisseur Docker fonctionne bien pour nous, nous n'aurons donc pas besoin de le configurer dans notre traefik.toml.

Avec le conteneur démarré, vous disposez désormais 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 frontends et les backends enregistrés par Traefik. Accédez au tableau de bord de surveillance en pointant votre navigateur sur https://monitor.example.com. 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.

Capture-d-e-cran-2018-03-20-a--18.27.32

Capture-d-e-cran-2018-03-20-a--18.28.09

Une fois connecté, vous verrez une interface similaire à ceci:

Capture-d-e-cran-2018-03-21-a--18.52.12

Il n'y a pas grand chose à voir pour l'instant, mais laissez cette fenêtre ouverte, et vous verrez le contenu changer à mesure que vous ajouterez des conteneurs pour que Traefik puisse fonctionner.

Nous avons maintenant notre proxy Traefik en cours d'exécution, configuré pour fonctionner avec Docker, et prêt à surveiller d'autres conteneurs Docker. Commençons quelques conteneurs pour Traefik pour agir comme un 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. Lancons les cotainers suivants derrière Traefik:

  • Un blog utilisant l'image Wordpress officielle.

  • Un serveur de gestion de base de données utilisant l'image officielle d'Adminer.

  • Nous allons gérer ces deux applications avec Docker Compose en utilisant un fichier docker-compose.yml:

    nano docker-compose.yml

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

docker-compose.yml
version: "3"

réseaux:
  Procuration:
    externe: true
  interne:
    externe: false

Nous utilisons la version 3 de Docker Compose car c'est la version majeure la plus récente du format de fichier Compose.

Pour que Traefik reconnaisse nos applications, celles-ci doivent faire partie du même réseau, et comme nous avons créé le réseau manuellement, nous l'incluons en spécifiant le nom de réseau du proxy et en définissant external sur true. Ensuite, nous définissons un autre réseau afin que nous puissions connecter nos conteneurs exposés à un conteneur de base de données que nous n'exposerons pas via Traefik. Nous appellerons ce réseau "interne".

Ensuite, nous allons définir chacun de nos services, un à la fois. Commençons par le conteneur de blog, sur lequel nous baserons l'image WordPress officielle. Ajoutez cette configuration au fichier:

docker-compose.yml
version: "3"
...

services:
  Blog:
    image: wordpress: 4.7.5-apache
    environnement:
      WORDPRESSDBPASSWORD:
    Étiquettes:
      - traefik.backend = blog
      - traefik.frontend.rule = Hôte: blog.example.com
      - traefik.docker.network = proxy
      - traefik.port = 80
    réseaux:
      - interne
      - Procuration
    dépends on:
      - mysql

La clé d'environnement 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, nous demandons à Docker Compose d'extraire la valeur de notre shell et de la transmettre lorsque nous créons le conteneur. Nous allons définir cette variable d'environnement dans notre shell avant de démarrer les conteneurs. De cette façon, nous ne codons pas les mots de passe 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 afin de savoir comment traiter les contenants. Voici ce que chacune de ces étiquettes fait:

traefik.backend spécifie le nom du service backend dans Traefik (qui pointe vers le conteneur de blog réel).
traefik.frontend.rule = Hôte: blog.example.com dit à Traefik d'examiner l'hôte demandé et s'il correspond au modèle de blog.example.com, il doit router le trafic vers le conteneur de blog.
traefik.docker.network = proxy spécifie quel réseau rechercher sous Traefik pour trouver l'adresse IP interne de ce conteneur. Puisque notre conteneur Traefik a accès à toutes les informations Docker, il pourrait potentiellement prendre l'IP pour le réseau interne si nous ne l'avons pas spécifié.
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é au port 80 de notre hôte Docker sera routé vers le conteneur de blog.

Nous affectons ce conteneur à deux réseaux différents afin que Traefik puisse le trouver via le réseau proxy et qu'il puisse communiquer avec le conteneur de la base de données via le réseau interne.

Enfin, la clé depends_on indique à Docker Compose que ce conteneur doit démarrer après l'exécution de ses dépendances. Puisque WordPress a besoin d'une base de données pour fonctionner, nous devons exécuter notre conteneur mysql avant de démarrer notre conteneur de blog.

Ensuite, configurez le service MySQL en ajoutant cette configuration à votre fichier:

docker-compose.yml
services:
...
  mysql:
    image: mysql: 5.7
    environnement:
      MYSQLROOTPASSWORD:
    réseaux:
      - interne
    Étiquettes:
      - traefik.enable = false

Nous utilisons l'image officielle MySQL 5.7 pour ce conteneur. Vous remarquerez que nous utilisons à nouveau un élément d'environnement sans valeur. Les variables MYSQL_ROOT_PASSWORD et WORDPRESS_DB_PASSWORD devront être définies avec la même valeur pour s'assurer que notre conteneur WordPress peut communiquer avec MySQL. Nous ne voulons pas exposer le conteneur mysql à Traefik ou au monde extérieur, donc nous assignons seulement ce conteneur au réseau interne. Puisque Traefik a accès au socket Docker, le processus affichera toujours une interface pour le conteneur mysql par défaut, nous allons donc ajouter l'étiquette traefik.enable = false pour spécifier que Traefik ne doit pas exposer ce conteneur.

Enfin, ajoutez cette configuration pour définir le conteneur Adminer:

docker-compose.yml
services:
...

  adminer:
    image: adminer: 4.3.1-autonome
    Étiquettes:
      - traefik.backend = adminer
      - traefik.frontend.rule = Hôte: db-admin.example.com
      - traefik.docker.network = proxy
      - traefik.port = 8080
    réseaux:
      - interne
      - Procuration
    dépend de:
      - mysql

Ce conteneur est basé sur l'image officielle Adminer. La configuration réseau et depends_on de ce conteneur correspond exactement à ce que nous utilisons pour le conteneur de blog.

Cependant, puisque nous dirigeons tout le trafic vers le port 80 sur notre hôte Docker directement vers le conteneur de blog, nous devons configurer ce conteneur différemment afin que le trafic puisse le faire dans notre conteneur adminer. Le fichier linetraefik.frontend.rule = Host: db-admin.example.com indique à Traefik d'examiner l'hôte demandé. Si elle correspond au modèle de db-admin.example.com Traefik acheminera le trafic vers le conteneur adminer.

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 avant de démarrer vos conteneurs:

export WORDPRESSDBPASSWORD=securedatabasepassword
export MYSQLROOTPASSWORD=securedatabasepassword

Remplacez secure_database_password par le mot de passe de votre base de données.

Avec ces variables définies, exécutez les conteneurs en utilisant docker-composer:

docker-compose up -d

Maintenant, jetez un coup d'œil au tableau de bord d'administration de Traefik. Vous verrez qu'il y a maintenant un backend et un frontend pour les deux serveurs exposés:

Capture-d-e-cran-2018-03-24-a--13.44.27

Capture-d-e-cran-2018-03-24-a--13.44.11

Accédez à blog.example.com, en remplaçant example.com par votre domaine. Vous allez être redirigé vers une connexion TLS et pouvez maintenant terminer l'installation de Wordpress:

Capture-d-e-cran-2018-03-24-a--15.02.50

Maintenant, accédez à Adminer en visitant db-admin.example.com dans votre navigateur, en remplaçant à nouveau example.com 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 interne Docker qu'ils partagent en utilisant le nom du conteneur mysql comme nom d'hôte.

Sur l'écran de connexion Adminer, utilisez le nom d'utilisateur root, utilisez mysql pour le serveur et utilisez la valeur que vous avez définie pour MYSQL_ROOT_PASSWORD pour le mot de passe. Une fois connecté, vous verrez l'interface utilisateur Adminer:

Capture-d-e-cran-2018-03-24-a--15.11.27

Et après configuration de notre site :

Capture-d-e-cran-2018-03-24-a--15.11.52

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

Conclusion

Dans ce didacticiel, nous avons configuré Traefik pour envoyer des demandes de proxy à d'autres applications dans des conteneurs Docker.

La configuration déclarative de Traefik au niveau du conteneur d'application facilite la configuration de plusieurs services et il n'est pas nécessaire de redémarrer le conteneur traefik lorsque vous ajoutez de nouvelles applications au trafic proxy car Traefik remarque immédiatement les modifications via le fichier socket Docker qu'il surveille.

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

Capture-d-e-cran-2018-03-24-a--15.20.03