Dev sandboxes auto-hébergées : créer des environnements de preview avec Docker et Go
"Le README de sandboxed explique le control plane Go, Docker, Traefik, SQLite, les URLs de preview, l'idle stop et les frontières de durcissement pour la production."
"La documentation de Docker sur les limites de ressources explique que les conteneurs n'ont aucune limite CPU ou mémoire par défaut et nécessitent des contraintes explicites."
"La documentation Docker Sandboxes décrit les microVMs, les daemons Docker isolés, le proxying réseau et l'isolation des credentials comme un modèle de sécurité plus fort."
"Le provider Docker de Traefik peut découvrir la configuration de routage depuis les labels Docker et router les services de conteneurs via des Host rules."
Les URLs de preview ressemblent à une fonctionnalité minuscule : lancer le port 3000 dans un conteneur, donner un lien à l’utilisateur, terminé. En pratique, une dev sandbox auto-hébergée fait vite remonter les collisions de ports, le routage de domaines, le recyclage des conteneurs, la persistance des fichiers et l’orchestration pilotée par API. Les produits de coding IA tombent dessus très vite : une fois que l’agent a écrit le code, l’utilisateur ne veut pas de logs. Il veut cliquer sur le résultat.
Un seul docker run ne suffit pas ici. Un design plus stable sépare quatre pièces : un hôte Linux, Docker pour les conteneurs, un control plane Go pour le cycle de vie, Traefik pour les domaines de preview et SQLite pour l’état. Ce setup convient aux équipes de confiance et à la validation produit early. Si vous comptez exécuter du code arbitraire d’utilisateurs inconnus, les conteneurs ne sont que la première couche. Pensez alors aux microVMs, aux hôtes dédiés ou à Kubernetes.
Pour beaucoup d’environnements éphémères, pas pour deux conteneurs personnels
Pour un projet personnel, deux conteneurs, deux ports et docker compose up -d suffisent souvent. Une dev sandbox commence à mériter sa place quand le nombre d’environnements grandit, que le cycle de vie raccourcit et qu’un système externe doit créer chaque environnement de façon programmatique.
| Scénario | Une dev sandbox auto-hébergée est-elle adaptée ? | Pourquoi |
|---|---|---|
| Une démo personnelle durable | Pas vraiment | Un script shell ou Compose est plus simple |
| Une preview par branche d’équipe | Oui | Il faut création, routage, recyclage et suivi d’état |
| Un AI app builder qui génère de petites apps pour les utilisateurs | Très adapté | L’agent doit écrire du code dans un répertoire isolé et exposer une URL de preview immédiatement |
| Exécuter du code arbitraire d’utilisateurs publics inconnus | Prototype seulement | Les conteneurs Docker ne sont pas une frontière d’isolation forte ; ajoutez VMs ou microVMs en production |
| Scheduling multi-nœuds, scaling élastique, politique réseau complexe | Le mono-hôte ne suffit pas | Kubernetes ou une plateforme managée est plus stable |
Beaucoup de développeurs demanderont d’abord pourquoi l’agent ne peut pas juste écrire un script shell. Question légitime. Un script résout « démarrer un conteneur ». Il ne résout pas « garder 50 environnements en vie, arrêter les inactifs, les réveiller à la prochaine requête, conserver les fichiers, donner à chaque environnement une URL stable et laisser un backend SaaS tout piloter via une API ». Une fois ces besoins empilés, le script commence à devenir un control plane.
La plus petite architecture : control plane Go, Docker, Traefik et SQLite
Le design de tastyeffectco/sandboxes est délibérément petit : un programme Go appelé sandboxd envoie des commandes Docker, Traefik route dynamiquement via les labels des conteneurs, SQLite stocke l’état et les workspaces vivent sur disque. Pas de Kubernetes, pas de serveur de base de données séparé, pas de message queue.
browser
|
v
Traefik ----> sandbox container ----> dev server :3000
^ ^
| |
sandboxd --------------+
|
+-- SQLite : état des sandboxes, ports, tâches
+-- workspaces/ : un répertoire persistant par sandbox
+-- reaper : idle stop / memory pressure stop
Quatre objets méritent d’être séparés.
Le control plane n’est pas le conteneur applicatif
Le control plane Go ne devrait gérer que le cycle de vie : créer une sandbox, l’arrêter, la détruire, exécuter une commande, soumettre une tâche d’agent, lire ou écrire des fichiers. Gardez-le mince. N’y enfouissez pas toute la logique de build. Les comportements plus complexes peuvent vivre dans l’image de base de la sandbox, une task queue ou la couche applicative au-dessus.
Une URL de preview n’est pas un port aléatoire
Chaque sandbox peut exposer une adresse comme s-<id>-3000.preview.localhost. Traefik lit les labels Docker, découvre le conteneur et le port cibles, puis transmet les requêtes via une Host rule. Les utilisateurs voient un lien stable au lieu de « ton port est 30017 ; n’entre pas en collision avec quelqu’un ».
SQLite est l’ancre d’état d’un petit système
Les conteneurs redémarrent. Les hôtes redémarrent. Traefik peut recharger. SQLite enregistre les IDs de sandbox, les ports, le statut, les tâches et les emplacements de workspace. Au démarrage du control plane, il peut réconcilier l’état réel de Docker avec cette base. SQLite convient à un produit early mono-hôte, tant que vous acceptez la frontière et que vous sauvegardez.
Le faire tourner en local : valider d’abord l’API, les ports et la résolution de domaine
Ne vous précipitez pas pour connecter un agent. Confirmez d’abord que le control plane peut démarrer des conteneurs, que Traefik peut transmettre et que l’URL de preview s’ouvre. Le quick start du README de sandboxes est direct :
git clone https://github.com/tastyeffectco/sandboxes.git
cd sandboxes
./install.sh
API=http://127.0.0.1:9090
curl "$API/healthz"
Après le passage du health check, créez une sandbox qui sert sur le port 3000 :
ID=$(curl -s -XPOST "$API/sandbox" \
-H 'content-type: application/json' \
-d '{"ports":[3000]}' | sed -E 's/.*"id":"([^"]+)".*/\1/')
curl -s -XPOST "$API/sandbox/$ID/exec" \
-H 'content-type: application/json' \
-d '{"cmd":["bash","-lc","cd ~/workspace && python3 -m http.server 3000"]}'
Puis ouvrez :
http://s-<id>-3000.preview.localhost
*.localhost se résout vers votre machine locale dans les navigateurs modernes, ce qui est utile pour des tests locaux sans DNS. Pour un vrai domaine, pointez *.preview.yourdomain.com vers l’hôte et laissez Traefik gérer TLS. N’exposez pas une API locale comme 127.0.0.1:9090 directement sur l’internet public. Au minimum, activez l’authentification par token en production et gardez le port du control plane derrière un pare-feu ou une passerelle privée.
Les URLs de preview sont difficiles à cause du routage, des réveils et de la persistance
Le port forwarding basique répond seulement à « comment accéder au conteneur pendant qu’il tourne ? » Une dev sandbox doit aussi répondre à « que se passe-t-il quand le conteneur dort ? », « où vivent les fichiers ? » et « le même utilisateur peut-il revenir plus tard ? ». Ces trois questions décident si le système passe de la démo à la bêta.
Routage : utiliser le domaine comme identité de l’environnement
Un port, c’est la perspective de la machine. Un domaine, c’est la perspective du produit. s-<id>-3000.preview.example.com contient l’ID de la sandbox et le port cible, donc l’application peut montrer le lien directement à l’utilisateur. Le provider Docker de Traefik lit les labels des conteneurs et transmet la Host rule au bon conteneur.
Dépannez dans cet ordre :
- DNS : le domaine wildcard pointe-t-il vers l’hôte, ou utilisez-vous
*.localhosten local ? - Traefik : le conteneur a-t-il les bons labels et est-il sur le même réseau Docker ?
- Port : l’app écoute-t-elle vraiment sur
0.0.0.0:3000, pas seulement sur127.0.0.1? - Readiness : avez-vous une page d’attente ou une stratégie de retry pendant le démarrage de l’app ?
- TLS : le vrai domaine utilise-t-il un certificat wildcard, et les entrypoints HTTP et HTTPS sont-ils cohérents ?
Réveil : l’idle stop n’est pas la suppression de l’environnement
Une sandbox inactive peut être arrêtée avec docker stop, ce qui libère de la mémoire tout en gardant le workspace sur disque. La prochaine fois qu’un utilisateur ouvre l’URL de preview, une route catch-all de faible priorité peut envoyer la requête au control plane. Le control plane démarre le conteneur, attend que le port soit prêt, puis laisse le navigateur entrer dans la vraie app.
Ce mécanisme consomme moins de ressources que « tout laisser allumé en permanence » et fait plus produit que « supprimer l’environnement dès qu’il se tait ». Le compromis est la latence de cold start, donc la page devrait afficher un état de warming au lieu de laisser l’utilisateur fixer un 502.
Persistance : les bind mounts sont utiles, mais connaissez la frontière
La documentation de Docker traite les bind mounts comme courants pour partager code source et artefacts de build. Une dev sandbox fait souvent pareil : un répertoire hôte par sandbox, monté dans le workspace du conteneur. L’avantage : le code survit à la suppression du conteneur. L’inconvénient : les chemins hôte et les permissions deviennent partie du design système.
Avant une bêta, fixez au moins trois règles : séparer les répertoires de workspace de la configuration du control plane ; faire de « supprimer le conteneur » et « supprimer le workspace » deux opérations distinctes ; sauvegarder workspaces et SQLite, pas seulement les couches de conteneur.
Bases du multi-tenant : limites de ressources, Docker socket, auth d’API et cache d’images
La documentation de Docker sur les limites de ressources est franche : les conteneurs n’ont aucune contrainte de ressources par défaut et peuvent utiliser CPU et mémoire autant que le scheduler du noyau hôte l’autorise. Dans un setup multi-tenant, c’est un risque. Le npm install, le build ou la boucle infinie d’un utilisateur peuvent ralentir toute la machine.
Commencez avec cette checklist :
- Définissez des limites mémoire, CPU et PID pour chaque sandbox.
- Gardez l’API du control plane sur localhost ou un réseau privé par défaut ; exigez l’authentification pour tout entrypoint public.
- Traitez les liens de preview comme partageables par défaut. Ajoutez le forward-auth quand ils contiennent du contenu sensible.
- Préinstallez les outils courants dans l’image de base pour que chaque sandbox n’ait pas à tout retirer à nouveau.
- Docker Hub a des rate limits officiels et des règles de fair use. En production, connectez-vous, préparez un cache d’images ou utilisez un registre privé.
- Montez les workspaces de sandbox séparément, et ne donnez jamais
/var/run/docker.sockaux conteneurs utilisateurs. - Journalisez création, arrêt, destruction, exécution de commandes et tâches d’agent.
Un exemple de limites de ressources en Compose peut ressembler à ceci :
services:
sandbox-app:
image: your-sandbox-base:latest
deploy:
resources:
limits:
cpus: "1.00"
memory: 1G
pids: 256
Le plus gros enjeu de sécurité est le Docker socket. Si sandboxd monte le Docker socket de l’hôte, il a une forte autorité sur l’hôte. C’est acceptable quand vous maintenez le control plane et que les utilisateurs n’entrent que dans les conteneurs de sandbox qu’il crée. Si les utilisateurs peuvent affecter le conteneur du control plane ou obtenir le Docker socket, le risque dépasse l’isolation de conteneur ordinaire.
Quand passer aux microVMs, à Kubernetes ou à une plateforme managée
L’avantage du Docker mono-hôte, c’est le coût, la lisibilité et la rapidité de changement. L’inconvénient est tout aussi clair : un hôte a une capacité limitée, la frontière de sécurité repose surtout sur l’isolation des conteneurs et la gouvernance de l’hôte, et le scheduling est plus faible qu’un cluster.
| Déclencheur | Meilleure direction |
|---|---|
| Exécuter du code arbitraire d’utilisateurs inconnus | microVMs, VMs dédiées, gVisor, Kata ou Firecracker |
| Les agents ont besoin de toute la capacité Docker sans toucher au daemon hôte | Style Docker Sandboxes : microVM plus daemon isolé |
| Scheduling multi-hôte, scaling élastique, politique réseau unifiée | Kubernetes |
| L’équipe ne veut pas maintenir le control plane bas niveau | Plateforme managée d’environnements de preview |
| Vous validez encore la demande produit | Docker mono-hôte plus un control plane Go |
Le modèle de sécurité officiel de Docker Sandboxes est un point de référence utile : il met l’agent IA dans une microVM, donne à chaque sandbox son propre daemon Docker, son système de fichiers et son réseau, et tient le daemon Docker hôte à l’écart de la sandbox. Cela coûte plus de ressources, mais la frontière d’isolation est plus claire.
Commencez donc par un setup mono-hôte pour apprendre la boucle produit : créer un environnement, laisser l’agent écrire du code, ouvrir la preview, recycler les sandboxes inactives et conserver les fichiers. Une fois que de vrais utilisateurs arrivent, montez en gamme la couche d’isolation selon le risque réel. Pas l’inverse : ne traînez pas l’équipe dans la maintenance de cluster avant que le problème d’échelle existe.
Une checklist pratique du MVP à la bêta
Vous pouvez avancer dans cet ordre sans tout construire d’un coup :
- Choisissez un hôte Linux propre qui ne fait tourner que des services liés à la sandbox. N’y co-localisez pas de bases de données, de CI runners ou d’applications de production.
- Configurez un domaine de preview wildcard comme
*.preview.example.com. Validez d’abord en local avec*.localhost. - Validez l’API du control plane : create, exec, stop, destroy et healthz.
- Préinstallez Node.js, Python, Git, les gestionnaires de paquets courants et les CLI d’agent que vous supportez dans l’image de base de la sandbox.
- Ajoutez limites de ressources, recyclage des inactifs, persistance de workspace et politique de destruction pour chaque sandbox.
- Activez l’authentification d’API, et ajoutez du contrôle d’accès aux liens de preview quand le métier l’exige.
- Journalisez les événements d’audit. Surveillez la mémoire de l’hôte, le disque, le nombre de conteneurs, le temps de cold start et le taux de 502.
- Répétez sauvegarde et restauration pour SQLite, les répertoires de workspace,
.envet les scripts de build de l’image de base.
Si votre prochaine étape est de connecter les previews de code à la CI, lisez GitHub Actions Self-Hosted Runner : le guide complet de déploiement en environnement privé. Si vous voulez héberger l’app Next.js générée sur le long terme, Quitter Vercel : le guide complet du self-hosting de Next.js avec Docker est plus proche de la seconde moitié du parcours. Pour les domaines publics et la protection de l’origine, continuez avec l’allowlisting d’IP d’origine Cloudflare.
FAQ
En quoi une Dev Sandbox diffère-t-elle de Docker Compose ?
Compose se rapproche de « je déclare un groupe de services, puis je les démarre ». Une Dev Sandbox se rapproche de « le backend produit crée, arrête, réveille et détruit des environnements à la demande, et chaque environnement obtient une URL ». Si les environnements sont peu nombreux et durables, Compose suffit. S’ils sont dynamiques par utilisateur, branche ou tâche d’agent, il faut un control plane.
Pourquoi ne pas utiliser Kubernetes ?
Si vous avez déjà un cluster, un ingress, un registre d’images, des permissions et du monitoring, Kubernetes est une base solide pour des environnements standardisés. Le problème, c’est que beaucoup d’équipes early veulent seulement valider un AI app builder ou un environnement de preview interne, et maintenir le cluster peut devenir plus lourd que le produit lui-même. Le Docker mono-hôte ne remplace pas Kubernetes ; il garde la première étape légère.
L’isolation des conteneurs peut-elle exécuter du code d’utilisateurs inconnus ?
Je ne le ferais pas directement. Les conteneurs conviennent aux équipes de confiance, aux utilisateurs internes ou aux démos à faible risque. Le code arbitraire d’utilisateurs inconnus devrait tourner dans une isolation plus forte : microVMs, VMs dédiées, gVisor, Kata, Firecracker, ou au moins des hôtes séparés par locataire.
Chaque URL de preview a-t-elle besoin de HTTPS ?
Les previews locales *.localhost peuvent démarrer en HTTP. Pour un vrai domaine public, utilisez HTTPS, surtout quand les utilisateurs saisissent des tokens, des formulaires ou des données métier. Un certificat wildcard réduit la peine d’émettre un certificat distinct pour chaque sandbox.
Les fichiers disparaissent-ils après un idle stop ?
Tant que le workspace est un répertoire persistant, docker stop ne supprime pas les fichiers. Le point délicat est la différence entre destroy et purge : l’un ne retire que le conteneur, l’autre retire aussi le workspace. Rendez cette distinction claire dans l’UI produit et les noms d’API.
Les rate limits de Docker Hub peuvent-elles affecter ce système ?
Oui. Quand beaucoup d’environnements démarrent, buildent et tirent des images souvent, le registre public peut devenir une dépendance instable. En production, connectez-vous à Docker Hub, préparez un registre privé ou un cache d’images, et intégrez les dépendances courantes dans l’image de base.
Conclusion
Une dev sandbox auto-hébergée vaut la peine d’être construite, mais ce n’est pas juste un docker run avancé. C’est une petite plateforme : le control plane possède le cycle de vie, le reverse proxy possède les URLs, le state store possède la restauration, et les limites de ressources plus la politique de sécurité empêchent un environnement de mettre l’hôte à genoux.
Le chemin stable est de construire d’abord la boucle produit avec du Docker mono-hôte, puis de monter en gamme selon le risque réel. Quand les utilisateurs sont peu nombreux, que le code est de confiance et que l’équipe accepte une frontière mono-hôte, Go + Docker + Traefik + SQLite suffit. Une fois que des utilisateurs inconnus, une isolation plus forte, le scheduling multi-hôte ou la gouvernance de conformité entrent en jeu, mettez microVMs, Kubernetes ou une plateforme managée sur la table.
Ressources
- tastyeffectco/sandboxes
- Docker Resource constraints
- Docker Engine security
- Docker Hub usage and limits
- Docker Sandboxes security model
- Traefik Docker provider
Construire un MVP de dev sandbox auto-hébergée
Un chemin pratique de la validation Docker mono-hôte aux contrôles de sécurité avant la bêta.
⏱️ Estimated time: 4 hr
- 1
Step1: Préparer un hôte propre
Utilisez un hôte Linux dédié aux services de sandbox. N'y co-localisez pas de bases de données de production, de CI runners ou d'autres services à forte valeur. - 2
Step2: Configurer le domaine de preview
Validez d'abord en local avec `*.localhost`. Pour un déploiement réel, pointez `*.preview.example.com` vers l'hôte et configurez TLS. - 3
Step3: Valider l'API du control plane
Testez au minimum create, exec, stop, destroy et healthz pour que le backend de votre application puisse gérer les environnements via l'API. - 4
Step4: Préparer l'image de base de la sandbox
Préinstallez Node.js, Python, Git, les gestionnaires de paquets courants et les CLI d'agent que vous comptez supporter. Cela réduit la configuration répétée après chaque démarrage de sandbox. - 5
Step5: Ajouter limites de ressources et recyclage
Définissez des limites CPU, mémoire et PID pour chaque sandbox. Ajoutez l'idle stop, le wake-on-request et la gestion de workspaces persistants. - 6
Step6: Verrouiller le control plane et les previews
Activez les tokens d'API, le réseau privé ou des règles de pare-feu. Pour les previews sensibles, ajoutez le forward-auth ou la couche de login de votre produit. - 7
Step7: Ajouter logs et monitoring
Journalisez create, stop, destroy, l'exécution de commandes et les tâches d'agent. Surveillez la mémoire de l'hôte, le disque, le nombre de conteneurs, le temps de cold start et le taux de 502. - 8
Step8: Répéter sauvegarde et restauration
Sauvegardez SQLite, les répertoires de workspace, `.env` et les scripts de build de l'image de base. Confirmez que vous pouvez les restaurer sur un nouvel hôte.
FAQ
En quoi une Dev Sandbox diffère-t-elle de Docker Compose ?
Pourquoi ne pas simplement utiliser Kubernetes ?
L'isolation des conteneurs Docker peut-elle exécuter directement du code d'utilisateurs inconnus ?
Chaque URL de preview a-t-elle besoin de HTTPS ?
Les fichiers disparaissent-ils après l'arrêt d'une sandbox inactive ?
Les rate limits de Docker Hub peuvent-elles affecter un système de Dev Sandbox ?
14 min de lecture · Publié le: 5 juin 2026 · Mis à jour le: 15 juin 2026
Commentaires
Connectez-vous avec GitHub pour laisser un commentaire