Tous les articles
ArchitectureDocker

Un reverse proxy Traefik mutualisé pour mes projets Docker en local

Comment un seul Traefik, versionné dans un repo d'infra dédié, route en HTTPS tous mes projets Docker locaux sans multiplier les ports ni les certificats — architecture et intégration dans un projet réel.

12 juillet 20264 min

Chaque nouveau projet Docker qui expose ses ports sur localhost finit par entrer en collision avec les précédents : 3000 déjà pris par un Next.js, 8000 par une API Laravel, 5432 par un Postgres qui traîne. Au bout de quelques projets actifs en parallèle, retenir quel port correspond à quoi devient plus pénible que le développement lui-même. La solution que j'utilise depuis un moment est un reverse proxy Traefik unique, mutualisé entre tous les projets, versionné dans son propre dépôt : docker-infra.

Un Traefik, un réseau partagé, zéro port à retenir

L'idée tient en une phrase : un seul conteneur Traefik écoute sur les ports 80/443 de la machine, et route chaque requête vers le bon service en fonction du nom de domaine demandé. Les projets, eux, n'exposent plus jamais leurs ports directement — ils rejoignent un réseau Docker externe nommé proxy, créé une fois pour toutes :

docker network create proxy

Le docker-compose.yml de Traefik dans docker-infra déclare le fournisseur Docker, les deux entrypoints HTTP/HTTPS et la redirection automatique vers HTTPS :

command:
  - --providers.docker=true
  - --providers.docker.exposedbydefault=false
  - --entrypoints.web.address=:80
  - --entrypoints.websecure.address=:443
  - --entrypoints.web.http.redirections.entrypoint.to=websecure
  - --entrypoints.web.http.redirections.entrypoint.scheme=https

exposedbydefault=false est le détail qui compte : aucun conteneur n'est routé tant qu'il ne porte pas explicitement un label traefik.enable=true. Sans ça, n'importe quel service qui rejoint le réseau proxy deviendrait accessible malgré lui.

HTTPS local avec mkcert, et la limite des wildcards

Router par nom de domaine ne suffit pas si le navigateur affiche un avertissement de certificat à chaque projet. docker-infra génère un certificat local de confiance via mkcert, piloté par un fichier domains.txt et un script regen.sh qui régénère le .pem et déclenche le rechargement à chaud de Traefik.

Le point technique qui a demandé un vrai ajustement : un wildcard X.509 ne couvre qu'un seul niveau de sous-domaine (RFC 6125). *.dev.localhost couvre api.dev.localhost, mais pas api.ops-board.dev.localhost, qui a un niveau de plus. La convention retenue est donc *.<projet>.dev.localhost par projet multi-services, chaque nouveau wildcard s'ajoutant simplement comme deux lignes dans domains.txt avant un regen.sh — pas besoin d'un certificat par projet.

Connecter un projet réel : labels Traefik dans son docker-compose

Côté projet, rien à configurer dans Traefik lui-même : tout se pilote par labels sur le conteneur à router. Le docker-compose.yml d'ops-board-api, une API Laravel, illustre le pattern sur son service Nginx :

nginx:
  networks:
    - default
    - proxy
  expose:
    - "80"
  labels:
    - traefik.enable=true
    - traefik.docker.network=proxy
    - traefik.http.routers.laravel.rule=Host(`api.ops-board.dev.localhost`)
    - traefik.http.routers.laravel.entrypoints=websecure
    - traefik.http.routers.laravel.tls=true
    - traefik.http.services.laravel.loadbalancer.server.port=80

Deux détails à ne pas rater : expose remplace ports (le port 80 reste interne au réseau Docker, jamais publié sur la machine), et traefik.docker.network=proxy lève l'ambiguïté quand le conteneur appartient à plusieurs réseaux — ici default pour parler à db, et proxy pour être routé. Le service db de ce même projet, lui, n'a aucun label Traefik : il n'a pas besoin d'être routé par domaine, un port mappé classique (5433:5432) suffit pour s'y connecter depuis l'hôte.

Ce que ça change au quotidien

Avec cette architecture, ajouter un projet ne demande plus de choisir un port disponible : juste un nom de domaine .dev.localhost et quelques labels. Le seul entretien récurrent est côté certificats — ajouter une ligne dans domains.txt pour un nouveau projet multi-sous-domaines. Le reste — routage, TLS, redirection HTTP — reste centralisé dans un seul dépôt, réinstallable à l'identique sur une nouvelle machine.

Prochaine étape

Besoin d'un renfort fiable sur votre produit ?

Si vous cherchez un développeur full-stack capable de s'intégrer rapidement, de livrer proprement, et de faire avancer un périmètre sans alourdir l'existant, discutons-en.

Voir mon CV