Tunnels de proxy Sidecar dans DevContainers : La norme moderne pour un développement local sécurisé

Arrêtez d’installer des outils de tunneling sur votre machine hôte. La pratique consistant à exécuter ngrok, cloudflared, ou tout autre démon de tunneling en tant que processus rogue sur votre ordinateur portable appartient au passé. En 2026, la bonne approche est de codifier toute votre topologie réseau — y compris l’accès au tunnel public — dans votre devcontainer.json. Ce guide explique comment faire cela correctement, quels outils choisir, et pourquoi cette évolution architecturale est importante.
Pourquoi l’ancienne méthode échoue
Le flux de travail classique pour un développeur ressemble à ceci : cloner un repo, installer les dépendances, installer ngrok globalement, lancer un tunnel, coller l’URL quelque part, et répéter à chaque expiration de session. Ça fonctionne — jusqu’à ce que ça ne fonctionne plus.
Les problèmes s’aggravent à mesure que les équipes grandissent :
- Non-reproductibilité. La version de l’outil de tunnel sur votre machine diffère de celle de votre collègue. Le comportement diverge. Les bugs sont imputés à la mauvaise couche.
- Dérive de sécurité. Un démon installé globalement avec accès réseau tourne sur votre OS hôte, en dehors de toute limite de conteneur. Ses identifiants sont stockés dans votre répertoire personnel, souvent non chiffrés.
- Conflits de ports. Des ports codés en dur comme
3000ou8080entrent en conflit entre projets. Vous commencez à vous souvenir de quel projet possède quel port. Ce n’est pas de l’ingénierie ; c’est de l’archéologie. - Frictions à l’intégration. Chaque nouveau développeur doit suivre un guide de configuration spécifique pour l’outil de tunnel. Ce guide devient obsolète.
La spécification DevContainer, maintenue conjointement par Microsoft et la communauté, résout cela au niveau de l’environnement. En définissant un dockerComposeFile dans devcontainer.json avec un service sidecar, vous faites du tunnel un composant de première classe, versionné, de votre chaîne d’approvisionnement logicielle — éphémère par défaut, reproductible par conception.
L’architecture : explication des conteneurs sidecar
Le pattern sidecar provient de l’architecture microservices. Un sidecar est un conteneur secondaire qui s’exécute à côté de votre conteneur principal, partageant son namespace réseau, mais gérant une préoccupation opérationnelle distincte — ici, le tunneling. Votre code applicatif ne touche jamais au tunnel. Le tunnel ne touche jamais à votre code applicatif. Les deux sont jetables ; aucun n’est une exception.
En termes Docker Compose, la disposition ressemble à ceci :
.devcontainer/
├── devcontainer.json
├── docker-compose.yml
└── (optionnel) Dockerfile
Le service app principal exécute votre code. Le sidecar du tunnel — que ce soit cloudflared, zrok, ou une alternative — s’exécute en tant que service dépendant, démarre après que l’application est saine, et se termine proprement lorsque la stack Compose est détruite.
Option 1 : Tunnel Cloudflare (cloudflared)
Le tunnel Cloudflare, accessible via le démon cloudflared, est l’option la plus déployée pour les équipes utilisant déjà Cloudflare pour DNS. Il établit des connexions sortantes uniquement vers le réseau edge de Cloudflare, sans règles de pare-feu entrantes ni adresses IP publiques.
Obtenir votre jeton
Créez un tunnel nommé via le tableau de bord Zero Trust de Cloudflare. Lors de la configuration, Cloudflare génère un TUNNEL_TOKEN. Copiez-le immédiatement — il ne sera plus affiché. Stockez-le comme variable d’environnement locale ou dans votre gestionnaire de secrets (secrets GitHub Codespaces, variables CI GitLab, etc.), jamais dans le dépôt.
docker-compose.yml
version: '3.8'
services:
app:
image: mcr.microsoft.com/devcontainers/node:20
volumes:
- ../:/workspace:cached
command: sleep infinity
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 10s
timeout: 5s
retries: 5
start_period: 15s
cloudflared:
image: cloudflare/cloudflared:latest
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
depends_on:
app:
condition: service_healthy
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
devcontainer.json
{
"name": "Node.js + Tunnel Cloudflare",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"remoteEnv": {
"CLOUDFLARE_TUNNEL_TOKEN": "${localEnv:CLOUDFLARE_TUNNEL_TOKEN}"
},
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint"
]
}
}
}
L’utilisation de ${localEnv:VARIABLE_NAME} indique au moteur DevContainer de lire la valeur depuis l’environnement hôte du développeur au démarrage et de l’injecter dans le contexte de Compose. Aucun identifiant ne transite dans le dépôt. Le tunnel s’authentifie, se connecte, et est prêt avant votre premier npm run dev.
Note sécurité : Toujours définir
network_modepour le conteneurcloudflaredafin de communiquer uniquement via le réseau Docker interne — pas avecnetwork_mode: host. Cela garantit que le sidecar du tunnel peut atteindre le conteneurapppar nom de service, mais ne peut pas sonder directement la pile réseau de l’hôte.
Option 2 : Zrok — Tunnels éphémères Zero-Trust
Alors que Cloudflare domine dans les environnements gérés, zrok — basé sur l’overlay réseau Zero Trust OpenZiti — a gagné en popularité auprès des développeurs souhaitant un contrôle total sur leur infrastructure ou des URLs entièrement éphémères et jetables. Zrok a atteint sa version 1.0 fin 2025, avec une nouvelle console Agent, une persistance réservée pour le partage, et des options d’auto-hébergement via Docker Compose avec Caddy pour TLS automatique.
La différence clé : lorsque vous arrêtez un partage zrok, cette URL disparaît immédiatement. Il n’y a pas d’enregistrement DNS persistant, pas de tunnel zombie, pas d’identifiants orphelins. Pour un contexte DevContainer — qui est lui-même éphémère — c’est précisément le comportement attendu.
Zrok supporte aussi les partages privés, où les ressources ne sont jamais exposées à un endpoint public et toute communication est chiffrée de bout en bout entre les clients zrok. Utile pour des environnements internes d’équipe où vous ne souhaitez pas de URL publique.
docker-compose.yml
version: '3.8'
services:
app:
image: mcr.microsoft.com/devcontainers/python:3.11
volumes:
- ../:/workspace:cached
command: sleep infinity
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/"]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
zrok-sidecar:
image: openziti/zrok:latest
environment:
- ZROK_ENABLE_TOKEN=${ZROK_TOKEN}
depends_on:
app:
condition: service_healthy
command:
sh -c "zrok enable $$ZROK_ENABLE_TOKEN
zrok share public http://app:8000 --headless"
Au démarrage de la stack, le sidecar active l’environnement zrok avec votre token, puis provisionne immédiatement une URL publique temporaire routant vers l’application Python sur le port 8000. L’URL est affichée dans les logs du conteneur. Lors du docker compose down, le processus zrok se termine et le partage est détruit.
Pour récupérer l’URL générée, inspectez les logs du sidecar :
docker logs <projet>-zrok-sidecar-1
Ou configurez le sidecar pour écrire l’URL dans un volume partagé que votre postStartCommand peut lire et afficher dans le terminal VS Code.
Option 3 : pgrok — Tunnels multi-locataires auto-hébergés
Pour les équipes souhaitant un tunneling de niveau entreprise sans le coût associé, pgrok offre une solution multi-locataires basée sur SSH que vous hébergez sur votre propre domaine. Il supporte l’authentification OIDC, permettant aux développeurs de s’authentifier via votre fournisseur SSO (Okta, Auth0, Google Workspace, etc.) avant qu’une URL de tunnel ne soit émise. Les URLs résultantes suivent le modèle https://feature-x.alice.dev.example.com — stables, lisibles, et liées à chaque développeur. Un opérateur Kubernetes peut injecter pgrok en sidecar automatiquement, donnant à chaque pod une URL révisable sans configuration spécifique.
Pour les équipes déjà en gestion d’un domaine et d’un fournisseur SSO, cela offre la majorité de l’expérience “ngrok d’entreprise” avec des coûts d’infrastructure de quelques dollars par mois.
Panorama des outils de tunneling en 2026
La pression concurrentielle sur ngrok s’est intensifiée. En février 2026, le projet open source DDEV a ouvert une issue pour envisager de supprimer ngrok comme fournisseur de partage par défaut, citant la réduction des limites du niveau gratuit. Le marché a répondu avec des alternatives viables à tous les prix :
| Outil | Modèle | Idéal pour | Niveau gratuit |
|---|---|---|---|
| Tunnel Cloudflare | SaaS géré | Équipes utilisant DNS Cloudflare | Oui (généreux) |
| zrok | Open source / SaaS | Éphémère, zero-trust, auto-hébergeable | Oui |
| pgrok | Auto-hébergé | Équipes avec domaine propre + SSO | Coût d’infrastructure uniquement |
| Tailscale Funnel | VPN Mesh | Accès privé d’équipe, basé sur WireGuard | Oui (personnel) |
| Inlets | Auto-hébergé / SaaS | Kubernetes natif, métriques Prometheus | Non (à partir de 25$/mois) |
| ngrok | SaaS géré | Bien documenté, support étendu | Restreint en 2026 |
Pour le test de webhook — cas d’usage DevContainer le plus courant — Cloudflare Tunnel (URL nommée persistante) et zrok (URL éphémère par session) sont de très bonnes options. Cloudflare est préférable quand vous devez configurer un endpoint webhook dans un service tiers (Stripe, GitHub) une seule fois et le laisser. Zrok est idéal quand vous souhaitez un état zéro persistant et une isolation maximale par session.
Bonnes pratiques
1. Toujours utiliser des vérifications de santé et des conditions depends_on
Le mode d’échec le plus fréquent dans les configurations de tunnels sidecar est le tunnel qui se met en ligne avant que l’application ne soit prête, entraînant des erreurs 502 Bad Gateway lors du démarrage. La solution consiste en des vérifications de santé explicites sur le service app et condition: service_healthy dans le bloc depends_on du sidecar. Ce n’est pas optionnel.
depends_on:
app:
condition: service_healthy
Sans cela, Docker Compose garantit uniquement l’ordre de démarrage des conteneurs, pas leur disponibilité.
2. Éviter les mappages de ports hôtes codés en dur
Si vous routez le trafic via un tunnel sidecar, vous n’avez pas besoin d’exposer les ports du conteneur à l’hôte avec ports: - "3000:3000". Supprimez ces mappages. Cela élimine complètement les conflits de ports — un autre projet peut utiliser le port 3000 sur la même machine sans conflit. Si vous avez aussi besoin d’un accès local via navigateur lors du développement, utilisez la fonction de forwarding de ports intégrée de VS Code plutôt qu’un mappage statique Docker.
3. Sécuriser l’injection de secrets
Le pattern ${localEnv:VARIABLE_NAME} dans devcontainer.json est la bonne approche pour tous les environnements. Pour GitHub Codespaces, stockez votre CLOUDFLARE_TUNNEL_TOKEN ou ZROK_TOKEN dans l’interface de secrets utilisateur — ils sont injectés automatiquement en tant que variables d’environnement au démarrage du Codespace, où ${localEnv:...} les récupère. Ne jamais écrire les tokens dans des fichiers .env suivis par git. Ajoutez .env à .gitignore et traitez-le comme un fichier local uniquement.
4. Visibilité des logs pour les conteneurs sidecar
Parce que le sidecar s’exécute en arrière-plan, ses logs n’apparaissent pas dans votre terminal principal VS Code. Les développeurs doivent les consulter activement. Trois options pratiques :
- Utiliser l’extension Docker dans VS Code pour suivre les logs de chaque conteneur depuis la barre latérale.
- Exécuter
docker logs <projet>-sidecar-1 --followdans un terminal hôte. - Configurer un
postStartCommanddansdevcontainer.jsonqui lit une URL écrite par le sidecar dans un volume partagé et l’affiche dans le terminal.
La troisième option offre la meilleure expérience développeur — l’URL publique apparaît dans le terminal VS Code automatiquement au démarrage du conteneur, sans inspection manuelle des logs.
5. Fixer les versions d’image en production
Pour l’expérimentation individuelle, cloudflare/cloudflared:latest ou openziti/zrok:latest conviennent. Pour les DevContainers d’équipe dans un dépôt, fixez à un digest ou une version spécifique. Cela évite qu’une mise à jour silencieuse de l’image en amont ne casse l’environnement de tout le monde simultanément, surtout que cloudflared et zrok publient fréquemment.
image: cloudflare/cloudflared:2025.2.0
Mise en pratique : un workflow complet
Voici l’expérience développeur de bout en bout lorsque tout est configuré correctement :
- Le développeur clone le dépôt.
- VS Code détecte
.devcontainer/devcontainer.jsonet propose de rouvrir dans le conteneur. - Docker Compose lance le conteneur
appet le sidecar du tunnel. - Le conteneur
appexécute sa vérification de santé ; une fois prêt, le sidecar démarre. - Le sidecar s’authentifie, provisionne le tunnel, et écrit l’URL publique dans un volume partagé.
- La commande
postStartCommandlit l’URL et l’affiche dans le terminal intégré. - Le développeur voit quelque chose comme
https://mon-projet.example.comen quelques secondes après le chargement de l’environnement. - Il colle cette URL dans la configuration webhook de Stripe et commence à coder.
- Lorsqu’il exécute
Ctrl+Cet que le conteneur s’arrête, le tunnel est détruit. Aucun nettoyage supplémentaire requis.
Pas d’outils installés sur l’hôte. Pas de gestion manuelle des tokens. Pas de conflits de ports. Pas d’URLs obsolètes pointant vers un ordinateur portable dont le couvercle est fermé.
Conclusion
Le pattern de proxy sidecar dans DevContainer n’est pas une curiosité architecturale niche — c’est la bonne méthode pour gérer le tunneling localhost en 2026. Que vous choisissiez Tunnel Cloudflare pour sa fiabilité gérée, zrok pour son modèle éphémère zero-trust, ou pgrok pour la maîtrise totale de l’infrastructure, le principe reste le même : l’infrastructure de tunneling doit être intégrée dans la définition du conteneur, versionnée avec le code applicatif, et non installée ad hoc sur la machine hôte du développeur.
Le résultat : onboarding plus rapide, meilleure posture de sécurité, comportement réseau reproductible, et fin des bugs de tunneling du genre “ça marche chez moi”. Docker a été conçu pour encapsuler précisément ce type de préoccupations opérationnelles. Utilisez-le.
Related InstaTunnel pages
Continue from this article into the most relevant product guides and workflows.
Related Topics
Keep building with InstaTunnel
Read the docs for implementation details or compare plans before you ship.