Pourquoi un reverse proxy est indispensable avec Docker
Par défaut, chaque conteneur Docker écoute sur un port arbitraire : votre Nextcloud est sur le port 8080, votre Gitea sur le 3000, votre Vaultwarden sur le 8200. Impossible d'exposer directement une dizaine de ports en production — les navigateurs n'acceptent pas les URL avec numéro de port, les certificats TLS couvrent des noms de domaine et non des ports, et votre pare-feu doit rester fermé sur tout sauf 80 et 443. Le reverse proxy résout ces trois problèmes d'un coup : il devient le seul point d'entrée public, route le trafic selon le nom d'hôte ou le chemin, et prend en charge la terminaison TLS. Résultat : app1.votre-domaine.com et app2.votre-domaine.com pointent toutes les deux sur le port 443 de votre VPS, et le proxy sait vers quel conteneur renvoyer chaque requête. Sans ce mécanisme, vous seriez contraint de gérer manuellement les certificats Let's Encrypt, d'ouvrir de multiples ports et de complexifier considérablement votre pare-feu.
Ce qu'un reverse proxy vous apporte concrètement
- Terminaison TLS centralisée — un seul outil obtient et renouvelle les certificats Let's Encrypt pour tous vos domaines automatiquement
- Routage par nom d'hôte —
git.votre-domaine.comva vers Gitea,cloud.votre-domaine.comva vers Nextcloud sans aucun conflit de port - Pare-feu simplifié — seuls les ports 80 et 443 sont ouverts au public, tous les ports internes Docker restent inaccessibles de l'extérieur
- Redirection HTTP → HTTPS automatique — tout le trafic non chiffré est redirigé en 301 sans configuration manuelle dans chaque application
- Observabilité centralisée — les logs d'accès et d'erreur de toutes vos applications sont agrégés en un seul endroit pour faciliter le débogage
Prérequis communs aux trois solutions
Avant de choisir et installer l'un de ces trois proxies, assurez-vous que votre VPS remplit quelques conditions de base. Docker et Docker Compose doivent être installés (version Compose V2 recommandée, soit la commande docker compose sans trait d'union). Vos enregistrements DNS doivent pointer vers l'IP publique de votre VPS avant de lancer la demande de certificat — Let's Encrypt vérifie le DNS lors de la validation HTTP-01, et une erreur à ce stade peut déclencher un rate limit qui bloque vos tentatives pendant plusieurs heures. Les ports 80 et 443 de votre VPS doivent être libres : vérifiez avec ss -tlnp | grep -E ':80|:443' qu'aucun autre service n'occupe déjà ces ports. Enfin, créez un réseau Docker dédié pour votre proxy — docker network create proxy — que vous attacherez à chaque conteneur que le proxy devra joindre.
Tableau comparatif : Caddy vs Traefik vs Nginx Proxy Manager
| Critère | Caddy | Traefik | Nginx Proxy Manager |
|---|---|---|---|
| Facilité d'installation | ⭐⭐⭐⭐⭐ Très simple | ⭐⭐⭐ Moyenne | ⭐⭐⭐⭐⭐ Très simple |
| TLS automatique (Let's Encrypt) | ✅ Natif, zéro config | ✅ Via ACME | ✅ Via interface web |
| Intégration Docker | Manuelle (labels ou config) | ✅ Labels natifs | ✅ Via GUI |
| Méthode de configuration | Fichier Caddyfile lisible | Labels Docker + YAML | Interface web graphique |
| Rechargement sans coupure | ✅ Automatique | ✅ Automatique | ✅ Automatique |
| Interface web/dashboard | ❌ Non | ✅ Dashboard inclus | ✅ Interface complète |
| Consommation mémoire | ~30 Mo | ~50 Mo | ~100 Mo (MariaDB inclus) |
| Idéal pour | Projets solo/petites équipes | Microservices, CI/CD | Débutants, équipes mixtes |
Caddy : la valeur par défaut pour la majorité des cas
Caddy s'est imposé comme le choix le plus simple pour les développeurs qui hébergent entre deux et dix applications sur un VPS. Sa philosophie est radicale : le TLS est activé par défaut pour tout domaine valide, sans aucune option à cocher ni variable à définir. Le fichier de configuration Caddyfile est intentionnellement lisible, proche de la langue naturelle, et peut tenir en une dizaine de lignes pour un cas d'usage courant. Caddy est écrit en Go et embarque son propre client ACME : il contacte Let's Encrypt directement, stocke les certificats dans son répertoire de données et les renouvelle automatiquement avant expiration. Contrairement à Nginx qui nécessite certbot en service séparé, Caddy n'a aucune dépendance externe pour le TLS. Sa consommation mémoire reste autour de 30 Mo au repos, ce qui le rend parfaitement adapté aux VPS d'entrée de gamme avec 1 ou 2 Go de RAM. Le seul vrai défaut de Caddy : la découverte automatique des conteneurs Docker n'est pas native. Pour y remédier, on utilise soit le plugin caddy-docker-proxy, soit une configuration statique dans le Caddyfile.
Déployer Caddy comme reverse proxy Docker
Créer le réseau Docker partagé
Avant tout, créez le réseau que Caddy et vos applications partageront : docker network create proxy. Ce réseau isolé permet à Caddy de joindre vos conteneurs par leur nom sans exposer leurs ports sur l'hôte.
Écrire le Caddyfile
Créez un fichier Caddyfile à la racine de votre projet. Pour exposer une application sur app.votre-domaine.com vers un conteneur nommé monapp écoutant sur le port 3000 : app.votre-domaine.com { reverse_proxy monapp:3000 }. Caddy obtient le certificat automatiquement au premier démarrage.
Écrire le docker-compose.yml pour Caddy
Créez un docker-compose.yml avec le service Caddy : montez le Caddyfile en lecture seule (./Caddyfile:/etc/caddy/Caddyfile:ro), persistez les données TLS dans un volume nommé (caddy_data:/data), publiez les ports 80 et 443, et attachez Caddy au réseau proxy en le déclarant comme réseau externe.
Attacher vos applications au réseau proxy
Dans le docker-compose.yml de chaque application, ajoutez le réseau proxy comme réseau externe et n'exposez plus les ports sur l'hôte (expose au lieu de ports). Caddy joindra le conteneur via le réseau interne Docker.
Démarrer et vérifier
Lancez Caddy avec docker compose up -d, puis suivez les logs avec docker compose logs -f caddy. Vous devriez voir certificate obtained successfully pour chaque domaine. Testez avec curl -I https://app.votre-domaine.com.
Ajouter une nouvelle application
Pour chaque nouvelle application, ajoutez un bloc dans le Caddyfile, rechargez Caddy sans coupure avec docker exec caddy caddy reload --config /etc/caddy/Caddyfile, et attachez le nouveau conteneur au réseau proxy.
Traefik : quand choisir la découverte automatique
Traefik brille dans les contextes où le nombre de services change fréquemment : environnements de CI/CD qui créent et détruisent des conteneurs à chaque déploiement, architectures microservices avec plus de cinq services indépendants, ou équipes où chaque développeur déploie ses propres stacks sans toucher à une configuration centralisée. Son mécanisme de découverte automatique via les labels Docker est son atout principal : quand vous démarrez un conteneur avec les bons labels (traefik.http.routers.monapp.rule=Host('app.votre-domaine.com')), Traefik le détecte instantanément et crée la route sans que vous ayez à toucher à sa configuration. Traefik inclut également un dashboard web qui visualise en temps réel tous les routers, services et middlewares actifs. En revanche, la courbe d'apprentissage est plus raide : les middlewares, les entrypoints et la syntaxe des labels peuvent dérouter les débutants, et une faute de frappe dans un label peut rendre une application silencieusement inaccessible.
Déployer Traefik avec découverte Docker automatique
Créer le fichier de configuration statique
Créez traefik.yml avec les entrypoints (web sur le port 80, websecure sur le 443), activez le provider Docker (docker: { exposedByDefault: false }), configurez le resolver ACME avec votre adresse e-mail pour Let's Encrypt, et activez le dashboard en mode sécurisé.
Lancer Traefik avec Docker Compose
Dans le docker-compose.yml de Traefik, montez le socket Docker en lecture seule (/var/run/docker.sock:/var/run/docker.sock:ro), montez traefik.yml, persistez les certificats dans un volume, et publiez les ports 80 et 443. Démarrez avec docker compose up -d.
Annoter vos conteneurs avec des labels
Sur chaque service à exposer, ajoutez les labels Traefik : traefik.enable=true, le rule du router (traefik.http.routers.monapp.rule=Host('app.votre-domaine.com')), l'entrypoint (websecure), le resolver TLS et le port interne du service.
Vérifier dans le dashboard
Accédez au dashboard Traefik (sur le port 8080 en local ou via un sous-domaine protégé) et vérifiez que votre router apparaît en vert avec le statut Enabled. Si le router est absent, vérifiez que le label traefik.enable=true est présent.
Sécurité critique : ne montez jamais le socket Docker (/var/run/docker.sock) sans restriction dans un environnement multi-utilisateurs — quiconque peut écrire dans ce socket peut prendre le contrôle total de l'hôte. En production, préférez le socket en lecture seule (ro) ou utilisez un proxy de socket comme docker-socket-proxy. Appliquez également un middleware d'authentification basique sur le dashboard Traefik avant de l'exposer publiquement.
Nginx Proxy Manager : l'option sans fichier de configuration
Nginx Proxy Manager (NPM) est le choix évident pour quiconque est mal à l'aise avec les fichiers de configuration en ligne de commande. Son interface web permet de créer un hôte proxy en quelques clics : vous entrez le nom de domaine, l'adresse du conteneur cible, cochez « Force SSL » et « HTTP/2 Support », cliquez sur « Save » — c'est tout. NPM gère le reste, y compris la demande de certificat Let's Encrypt. L'interface permet également de gérer plusieurs utilisateurs avec des droits différents, d'ajouter des listes de contrôle d'accès et de configurer des redirections. En revanche, NPM embarque une base de données MariaDB pour stocker sa configuration, ce qui porte sa consommation mémoire autour de 100 Mo — presque le triple de Caddy. NPM convient parfaitement aux équipes mixtes techniques/non-techniques ou aux contextes où d'autres personnes que le sysadmin principal doivent gérer des domaines.
Dépannage : les erreurs les plus fréquentes
La majorité des problèmes rencontrés appartient à quatre catégories. Premièrement, les rate limits Let's Encrypt : si vous relancez votre stack plusieurs fois en test avec le même domaine, vous pouvez épuiser la limite de cinq certificats par domaine sur sept jours. Solution : utilisez l'environnement de staging Let's Encrypt (acme_ca https://acme-staging-v02.api.letsencrypt.org/directory dans Caddy) pour vos tests. Deuxièmement, les conflits de ports : si le port 80 ou 443 est déjà occupé par Apache ou Nginx de l'hôte, le proxy Docker ne démarrera pas. Identifiez le processus avec ss -tlnp | grep :80. Troisièmement, les erreurs de réseau Docker : vérifiez que le proxy et le conteneur cible sont sur le même réseau avec docker network inspect proxy. Quatrièmement, pour Traefik, les fautes de frappe dans les labels — activez les logs en mode DEBUG avec --log.level=DEBUG.
Récapitulatif : quel proxy pour quel profil
- Développeur solo, 2 à 5 apps — Caddy : configuration minimale, TLS automatique, démarrage en moins de dix minutes avec un Caddyfile de quinze lignes
- Équipe DevOps, microservices, CI/CD — Traefik : découverte automatique via labels, dashboard de supervision, parfait quand le nombre de services varie dynamiquement
- Utilisateur non-technique ou équipe mixte — Nginx Proxy Manager : interface graphique intuitive, aucun fichier à éditer, gestion multi-utilisateurs intégrée
- VPS avec peu de RAM (512 Mo à 1 Go) — Caddy ou Traefik : évitez NPM qui embarque MariaDB et consomme davantage de mémoire
- Migration progressive depuis Nginx — Caddy : sa syntaxe s'apprend en une heure et il peut cohabiter temporairement avec Nginx sur des ports différents
Conclusion : commencez par Caddy, évoluez si nécessaire
Pour la très grande majorité des self-hosters qui gèrent quelques applications Docker sur un VPS, Caddy est le idéal point de départ : il est simple, léger, opinionné dans le bon sens et gère le TLS mieux que n'importe quelle alternative sans configuration supplémentaire. Si votre infrastructure grandit au-delà de cinq services avec des déploiements fréquents et automatisés, Traefik devient plus adapté grâce à sa découverte dynamique. Si vous devez déléguer la gestion des domaines à des personnes non-techniques, Nginx Proxy Manager est la seule option vraiment accessible.