NoctisNode
← GuidesAuto-hébergement2026-10-239 min

Caddy en reverse proxy Docker : configuration Compose avec HTTPS automatique

Faites tourner Caddy comme reverse proxy Docker : une stack compose, un réseau partagé, reverse_proxy vers les noms de service et HTTPS automatique, et quand les labels de caddy-docker-proxy sont utiles.

En bref : faites tourner Caddy dans son propre conteneur qui publie les ports 80 et 443, rattachez-le avec vos conteneurs applicatifs à un même réseau Docker partagé, et pointez `reverse_proxy` vers chaque nom de service et son port interne (par exemple `reverse_proxy app:3000`). Caddy résout le nom via le DNS intégré de Docker et obtient automatiquement un certificat TLS pour chaque adresse de site.

Ce guide présente d'abord l'approche par Caddyfile simple, puis la variante caddy-docker-proxy pilotée par labels, et explique quand chacune convient sur un seul VPS. Si vous faites tourner Caddy directement sur l'hôte plutôt que dans Docker, voir le guide reverse proxy Caddy de base.

Comment les éléments s'articulent

Seul le conteneur Caddy publie des ports vers l'extérieur. Chaque conteneur backend rejoint un réseau bridge défini par l'utilisateur (ici nommé `web`) et n'expose son port que sur ce réseau. Le serveur DNS intégré de Docker, disponible sur les réseaux définis par l'utilisateur, permet à Caddy de joindre `app:3000` par nom de service ou de conteneur : vous ne codez jamais en dur des IP de conteneurs qui changent à chaque recréation.

Ne pas publier les backends compte plus qu'il n'y paraît : Docker écrit ses propres règles iptables, si bien qu'un port publié avec `ports:` peut être joignable depuis Internet même quand ufw indique qu'il est bloqué. Utilisez `expose:` ou aucun mappage de port pour tout ce qui doit rester derrière le proxy.

ComposantRôlePublié sur l'hôte ?
conteneur caddyTerminaison TLS, routage par nom d'hôte, redirection HTTP vers HTTPSOui : 80/tcp, 443/tcp, 443/udp
réseau webRéseau bridge partagé avec DNS intégré pour les noms de serviceNon
conteneurs applicatifsVos services (applications web, API, tableaux de bord)Non, joignables uniquement via Caddy
volume caddy_dataCertificats, clés privées, compte ACMENon, mais doit persister

Pas à pas : Caddyfile simple avec docker compose

  1. 01.Pointez un enregistrement A (et AAAA si vous utilisez IPv6) pour chaque nom d'hôte vers le VPS avant de démarrer Caddy, sinon l'émission des certificats échouera.
  2. 02.Créez une fois le réseau partagé : `docker network create web`.
  3. 03.Créez `/opt/proxy/compose.yaml` et `/opt/proxy/Caddyfile` comme ci-dessous, puis lancez `docker compose up -d` dans `/opt/proxy`.
  4. 04.Rattachez chaque stack applicative au réseau externe `web` et démarrez-la avec `docker compose up -d`.
  5. 05.Suivez l'émission du premier certificat avec `docker compose logs -f caddy` dans `/opt/proxy`.
  6. 06.Après modification du Caddyfile, rechargez sans interruption : `docker compose exec -w /etc/caddy caddy caddy reload`.
# /opt/proxy/compose.yaml
services:
  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"   # HTTP/3
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data      # certificates and ACME account keys
      - caddy_config:/config
    networks:
      - web

volumes:
  caddy_data:
  caddy_config:

networks:
  web:
    external: true

Rattacher une application et écrire le Caddyfile

Chaque stack applicative déclare le même réseau externe. Le nom du service devient le nom d'hôte que Caddy contacte. Le volume `caddy_data` est celui que vous ne devez jamais perdre : le supprimer oblige Caddy à redemander tous les certificats, ce qui peut se heurter aux limites de débit ACME.

# /opt/app/compose.yaml
services:
  app:
    image: ghcr.io/example/app:latest
    restart: unless-stopped
    expose:
      - "3000"        # reachable on the network, NOT published on the host
    networks:
      - web

networks:
  web:
    external: true

# /opt/proxy/Caddyfile
{
	email [email protected]
}

app.example.com {
	reverse_proxy app:3000
}

grafana.example.com {
	reverse_proxy grafana:3000
}

api.example.com {
	reverse_proxy api-1:8080 api-2:8080 {
		lb_policy round_robin
		health_uri /healthz
		health_interval 10s
	}
}

Backends Caddy : upstreams, répartition de charge et health checks

Dans le vocabulaire de Caddy, un backend est un upstream de `reverse_proxy`. Vous pouvez lister plusieurs upstreams dans une seule directive, choisir une `lb_policy` comme `round_robin`, `least_conn` ou `ip_hash`, et ajouter des health checks actifs avec `health_uri` pour que les conteneurs défaillants sortent de la rotation. Les vérifications passives (`fail_duration`, `max_fails`) sont utiles aussi quand l'application n'a pas d'endpoint de santé.

Caddy définit par défaut `X-Forwarded-For`, `X-Forwarded-Proto` et `X-Forwarded-Host` sur les requêtes proxifiées. Configurez votre application pour qu'elle fasse confiance à la plage réseau du proxy, afin qu'elle voie la vraie IP du client et génère des liens `https://`. WebSockets et gRPC fonctionnent via `reverse_proxy` sans réglage supplémentaire ; pour du gRPC en clair, utilisez `reverse_proxy h2c://service:50051`.

Des labels au lieu d'un Caddyfile : caddy-docker-proxy

Ceux qui cherchent un « Caddy proxy manager » veulent généralement ce que propose Nginx Proxy Manager : ajouter un conteneur et obtenir un nom d'hôte et un certificat sans modifier de fichier central. Caddy n'a pas d'interface graphique officielle, mais le projet communautaire caddy-docker-proxy (github.com/lucaslorentz/caddy-docker-proxy) génère le Caddyfile à partir des labels des conteneurs et recharge Caddy quand des conteneurs démarrent ou s'arrêtent.

Il a besoin d'un accès en lecture au socket Docker, ce qui équivaut de fait à root sur l'hôte. Montez-le en lecture seule, maintenez l'image du proxy à jour, et préférez le Caddyfile simple si vous ne faites tourner qu'une poignée de services.

services:
  caddy:
    image: lucaslorentz/caddy-docker-proxy:ci-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    environment:
      - CADDY_INGRESS_NETWORKS=web
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - caddy_data:/data
    networks:
      - web

  whoami:
    image: traefik/whoami
    networks:
      - web
    labels:
      caddy: whoami.example.com
      caddy.reverse_proxy: "{{upstreams 80}}"

volumes:
  caddy_data:

networks:
  web:
    external: true

Caddyfile simple ou caddy-docker-proxy

Caddyfile simpleLabels caddy-docker-proxy
La configuration se trouve dansUn seul fichier versionné dans gitDes labels répartis dans les fichiers compose
Accès au socket DockerInutileRequis (sensible pour la sécurité)
Nouveau serviceModifier le Caddyfile, lancer `caddy reload`Ajouter des labels, démarrer le conteneur
Image`caddy:2` officielleImage communautaire basée sur Caddy
DébogageLire directement le fichierExaminer la configuration générée dans les journaux
Idéal pourPetits VPS stablesNombreux services éphémères ou souvent modifiés

Le faire tourner sur un VPS

Sur un VPS KVM NoctisNode, vous disposez d'un accès root complet et d'une IPv4 dédiée : publier 80 et 443 depuis un seul conteneur Caddy et masquer tout le reste est simple. Un Wisp (1 vCPU, 1 Go de RAM) suffit pour Caddy et quelques conteneurs légers ; les stacks plus lourdes conviennent à Pulse ou Umbra. Les détails d'émission des certificats et les pannes possibles sont couverts dans comment fonctionne le HTTPS automatique de Caddy, et le transfert TCP brut ou SSH dans proxy TCP et SSH avec Caddy. Verrouillez le SSH de l'hôte avec le guide de durcissement SSH.

FAQ

QComment faire de Caddy un reverse proxy vers un conteneur Docker ?

APlacez Caddy et le conteneur sur le même réseau Docker défini par l'utilisateur et utilisez `reverse_proxy service-name:port` dans le Caddyfile. N'utilisez pas `localhost`, car dans le conteneur Caddy il désigne Caddy lui-même.

QPourquoi Caddy renvoie-t-il 502 Bad Gateway pour mon conteneur ?

AEn général, les conteneurs ne sont pas sur un réseau partagé, le port est erroné (utilisez le port interne du conteneur, pas un port publié sur l'hôte), ou l'application n'écoute que sur 127.0.0.1 dans son conteneur. Faites-la écouter sur 0.0.0.0 et vérifiez `docker network inspect web`.

Qcaddy-docker-proxy est-il sûr ?

AIl fonctionne bien, mais il nécessite le socket Docker, qui donne un contrôle équivalent à root sur l'hôte. Montez-le en lecture seule, maintenez l'image à jour et évitez d'exposer l'endpoint d'administration de Caddy.

QOù Caddy stocke-t-il les certificats dans Docker ?

ADans `/data` à l'intérieur de l'image officielle : montez-y un volume nommé. Le perdre signifie réémettre tous les certificats, avec le risque d'atteindre les limites de débit ACME.

QExiste-t-il un Caddy proxy manager avec interface web ?

ACaddy n'a pas d'interface web officielle ; il se configure avec un Caddyfile, du JSON ou son API d'administration. Des outils à base de labels comme caddy-docker-proxy offrent un fonctionnement similaire : on ajoute un conteneur et c'est parti.

Caddy en reverse proxy Docker : configuration Compose avec HTTPS automatique · NoctisNode