Comment mettre le HTTPS en local avec docker-compose et mkcert ?
Publié le
27 mars 2023
Docker et docker-compose sont maintenant largement utilisés dans le monde du développement web. Depuis notre premier hackathon en 2015, Docker est devenu un standard dans tous nos projets.
Cela nous aide énormément pour maintenir nos différentes stacks et pour gérer des configurations spécifiques pour les environnements de développement, staging ou production.
Néanmoins, beaucoup de configurations Docker pour des environnements de développement sont assez éloignés des environnements de staging ou de production.Cet article explique pourquoi les différents environnements doivent être proches les uns des autres. C'est le meilleur moyen de fail fast en local pour éviter de déployer des bugs en production.
La plupart du temps, la configuration locale de Docker donne accès aux services en utilisant des ports spécifiques. Le Saint Graal est d'utiliser un reverse-proxy (comme Traefik) même en développement. C'est pourquoi aujourd'hui, on se concentre sur un sujet très spécifique : Le cryptage TLS en environnement local.
Prérequis
Cet article a été créé en utilisant ces versions de Docker et Mkcert
docker
: 20.10.15docker-compose
: 1.28.5mkcert
: 1.4.3-1
La configuration présentée peut fonctionner avec des versions plus anciennes mais nous n'avons pas vérifié.
Traefik
Avant de commencer, nous devons nous attarder un minimum sur Traefik si vous n'en avez jamais entendu parler.
Fondamentalement, Traefik est un reverse proxy, concrètement c'est la porte d'entrée de votre plateforme.
Il intercepte et redirige toutes les requêtes entrantes : il connaît toute la logique et toutes les règles qui déterminent quel service traite quelles requêtes (basé sur le chemin, l'hôte, le header etc.).
Ce qui est cool avec Traefik c'est que vous n'avez pas beaucoup de configuration à écrire pour le faire marcher.
Avec seulement quelques labels docker-compose sur vos service, vous avez un puissant reverse-proxy pour traiter le traffic de votre stack.
Mkcert
mkcert
est un outil pour générer des certificats de développement localement fiables qui pourront ensuite être partagés à Traefik pour effectuer un cryptage TLS.
Mkcert peut aussi etre utilisé en environnement local. Les domaines publiques demanderont de leur fournir un certificat approuvé par une authorité externe.
Vous pouvez suivre le guide d'installation sur la documentation de mkcert.
Pour commencer
Nous allons utiliser l'image Docker containous/whoami
pour faire une démonstration de l'utilisation d'un certificat TLS sur un service docker-compose.
Certificats Mkcert
Premièrement nous devons créer et stocker les certificats TLS créé par mkcert
dans le dossier ./certs
.
Ces certificats sont localement fiables c'est à dire qu'ils sont valides uniquement sur votre machine. Par conséquent, vous devez les ajouter à votre gitignore
.
mkdir -p certs
mkcert -cert-file certs/local-cert.pem -key-file certs/local-key.pem "app.localhost" "*.app.localhost" "domain.local" "*.domain.local"
Configuration Traefik
Maintenant créez les dossiers : ./docker/traefik
mkdir -p docker/traefik
Créez ensuite le fichier ./docker/traefik/dynamic_conf.yaml
qui permettra la configuration de tous les sous-domaines servis par Traefik.
Il indique aussi le chemin vers les certificats TLS (générés par Mkcert) qui seront ensuite partagés avec Traefik via un volume Docker.
http:
routers:
traefik:
rule: "Host(`traefik.app.localhost`)"
service: "api@internal"
tls:
domains:
- main: "app.localhost"
sans:
- "*.app.localhost"
- main: "domain.local"
sans:
- "*.domain.local"
tls:
certificates:
- certFile: "/etc/certs/local-cert.pem"
keyFile: "/etc/certs/local-key.pem"
Puis nous allons créer le fichier de configuration ./docker/traefik/traefik.yaml
.
global:
sendAnonymousUsage: false
api:
dashboard: true
insecure: true
providers:
docker:
endpoint: unix:///var/run/docker.sock
watch: true
exposedbydefault: false
file:
filename: /etc/traefik/dynamic_conf.yaml
watch: true
log:
level: DEBUG
format: common
entryPoints:
web:
address: ':80'
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ':443'
Je ne vais pas expliquer chaque partie de ce fichier mais je vais un peu expliciter les sections providers
et entryPoints
:
providers
Cette section indique à Traefik quels services sont accessibles de l'extérieur et comment ils sont accessibles. C'est globalement la configuration du routeur.
Nous avons ici deux providers différents :
docker
: Utilise des labels sur les conteneurs pour récupérer les configurations de routage (plus d'information dans la prochaine section).file
: Charge un fichier de configuration, ici le fichierdynamic_config.yaml
que l'on vient de créer.
entryPoints
Cette section est plutôt simple, elle permet de rediriger toutes les requêtes entrantes de http
(port 80) en https
(port 443).
Maintenant nous pouvons être sûr que Traefik ne transmettra aucune requête http
à vos services.
Fichier docker-compose
Remplir le fichier docker-compose.dev.yml
avec :
version: '3.8'
services:
reverse-proxy:
image: traefik:v2.4.7
container_name: traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik=true"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
ports:
- 80:80
- 443:443
restart: unless-stopped
security_opt:
- no-new-privileges:true
volumes:
- ./docker/traefik/dynamic_conf.yaml:/etc/traefik/dynamic_conf.yaml:ro
- ./docker/traefik/traefik.yaml:/etc/traefik/traefik.yaml:ro
- ./certs:/etc/certs:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
whoami:
image: containous/whoami:latest
container_name: whoami
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.app.localhost`)"
- "traefik.http.routers.whoami.tls=true"
restart: unless-stopped
networks:
proxy:
external: true
Vous trouverez ainsi les déclarations des services de votre stack. Voici quelques explications sur cette configuration :
reverse-proxy
- ports : Relie les ports 80 et 443 avec l'hôte. A noter que le service
whoami
n'expose aucun port. Toutes les requêtes entrantes de votre stack seront gérées par Traefik. - volumes : Nous partageons les fichiers de configurations, les certificats et le socket Docker (Traefik a besoin d'un accès au socket Docker pour avoir accès à sa configuration dynamique).
whoami
Nous définissons trois labels:
traefik.enable=true
: On définie explicitement à Traefik d'exposer publiquement ce conteneur.traefik.http.routers.whoami.rule=Host('whoami.app.localhost')
: Le domaine rattaché au service.traefik.http.routers.whoami.tls=true
: Active le HTTPS sur cette route.
Lancer la stack
docker-compose -f docker-compose.dev.yml up -p
Et voilà! Vous pouvez maintenant accéder à : https://whoami.app.localhost.
Des questions ou des retours ? N'hésitez pas à nous envoyer un message sur Twitter ! https://twitter.com/KNPLabs
Commentaires