Dev Sandbox auto-hébergé avec Docker et Go : des preview URL sans Kubernetes

"Le README de sandboxed décrit le plan de contrôle Go, Docker, Traefik, SQLite, les preview URL, l'idle stop et les limites de hardening en production."
"La documentation Docker sur les limites de ressources explique que les containers n'ont pas de limites CPU ou mémoire sans configuration explicite."
"La documentation Docker Sandboxes présente les microVM, le Docker daemon indépendant, l'isolation réseau et l'isolation des credentials comme un modèle plus fort."
"Le Docker provider de Traefik peut lire la configuration de routage depuis les Docker labels et utiliser des Host rules vers les services container."
Ouvrir un environnement de preview par PR se fait souvent avec Vercel ou Netlify. Si le coût, les données en réseau privé ou le contrôle de l’infrastructure priment, un host Docker unique avec un plan de contrôle Go peut remplacer cette couche au début. Chaque sandbox a sa propre preview URL, les ressources ont des limites et la frontière de sécurité est explicite. Pas de Kubernetes, pas de multi-nœud.
Tableau de décision — quelle solution selon le contexte
Quand le besoin “environnements de preview auto-hébergés” arrive, le premier réflexe est souvent d’empiler des docker run dans un script shell, ou au contraire de partir directement sur Kubernetes. Commencez plutôt par ce tableau.
| Contexte | Solution recommandée | Pourquoi |
|---|---|---|
| Équipe interne avec moins de 10 previews simultanées, frontière de confiance dans l’équipe | Docker sur un host + plan de contrôle Go | Densité de ressources maîtrisable, architecture simple, pas besoin d’exploiter un cluster K8s |
| Équipe interne avec plus de 20 previews simultanées, ou besoin de haute disponibilité multi-nœud | K8s + isolation par Namespace | Un seul host ne suffit plus ; il faut scheduler sur plusieurs nœuds et gérer les mises à jour |
| Utilisateurs externes ou exécution de code non fiable, comme des autonomous agents | microVM, par exemple Docker Sandboxes ou Firecracker | Docker socket équivaut à un pouvoir très élevé sur le host ; ne le mélangez pas avec des workloads non fiables |
| Preview statique simple sans persistance | Script shell + port aléatoire | Ça peut fonctionner, mais l’URL n’est pas stable et les limites de ressources comme la sécurité restent faibles |
Trois critères suffisent.
Taille de l’équipe : un host unique convient surtout à moins de 10 previews internes simultanées. Un calcul simple : 512 MB de RAM et 0,5 CPU par sandbox. Un host de 16 GB peut porter environ 20 sandboxes avant que la marge devienne mince. Au-delà, il faut du scheduling K8s ou répartir la capacité avec des microVM.
Frontière de confiance : les membres d’une équipe interne et les utilisateurs de confiance peuvent tourner dans des containers Docker. Si des inconnus externes ou des autonomous agents exécutent du code arbitraire, la conception avec Docker socket n’est pas assez sûre. Docker Sandboxes utilise une isolation microVM ; chaque sandbox reçoit son propre Docker daemon, son système de fichiers et son réseau.
Chemin d’évolution : commencez par Docker sur un seul host pour valider la boucle produit et la densité. Quand la concurrence dépasse le host ou que la haute disponibilité multi-nœud devient nécessaire, passez à Kubernetes. Quand la frontière de confiance passe de “équipe interne” à “utilisateurs externes”, passez aux microVM.
Le README de tastyeffectco/sandboxes décrit clairement la cible : AI app builders, agent platforms et coding playgrounds sur Docker single-host. Ce n’est pas une isolation de niveau microVM ; c’est un plan de contrôle Go qui crée des containers sur un Docker host unique et expose des preview URL.
Architecture — les composants centraux du plan de contrôle
Un environnement de preview Docker single-host n’est pas une simple boucle autour de docker run. Il faut un plan de contrôle pour le cycle de vie, l’enregistrement des routes et la récupération des ressources. L’architecture de tastyeffectco/sandboxes se découpe en six modules.
Plan de contrôle Go (sandboxd) : il tourne dans un container et monte le Docker socket du host ainsi qu’un répertoire de données. Il pilote le cycle de vie des containers sandbox via Docker CLI : créer, démarrer, arrêter, supprimer. Toutes les métadonnées de sandbox vont dans SQLite, qui sert de source of truth.
Montage du Docker socket : c’est l’entrée du plan de contrôle vers le Docker daemon. En montant /var/run/docker.sock, sandboxd obtient le droit de créer et gérer des containers. C’est aussi la frontière de privilège principale : avec ce socket, le plan de contrôle a des permissions très élevées sur le host.
Enregistrement par labels Traefik : au démarrage de chaque sandbox container, le plan de contrôle injecte la configuration de routage Traefik via Docker labels. Traefik joue le rôle de reverse proxy, découvre les routes depuis les labels et redirige *.preview.example.com vers le bon container.
Stockage des métadonnées dans SQLite : chaque sandbox a un ID unique et un répertoire associé. Les métadonnées sont stockées dans SQLite. Les workspaces vivent sous SANDBOXED_DATA_DIR/workspaces/, avec un sous-répertoire par sandbox pour le code source, la configuration et les artefacts.
Idle reaper et pressure reaper : l’idle reaper vérifie depuis combien de temps un sandbox container est inactif et l’arrête au-delà du seuil pour libérer la RAM. Le pressure reaper surveille la pression mémoire du host et arrête certaines sandboxes avant un OOM host. Ces deux reapers sont le cœur de la récupération de ressources.
Wake path : après l’arrêt d’un sandbox container par l’idle reaper, la première visite de la preview URL doit le réveiller. Un catch-all Traefik transmet la requête au plan de contrôle ; celui-ci démarre le container et renvoie une warming page jusqu’à ce que l’app soit prête.
La version minimale utile : container de plan de contrôle Go, Docker socket mount, Traefik, SQLite et idle reaper. Le quick start local demande Docker Engine et le plugin Compose.
Implémenter les preview URL
Le point clé d’une preview URL est un domaine stable, pas un port aléatoire. Chaque sandbox possède son propre {sandbox_id}.preview.example.com.
Configuration du Docker provider Traefik
Traefik peut découvrir la configuration de routage depuis les labels de containers via le Docker provider. Exemple minimal :
# traefik.yml
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
exposedByDefault: false signifie que Traefik ne découvre que les containers explicitement marqués par des labels.
Host rule et Docker labels
Le plan de contrôle injecte les labels lors de la création du sandbox container. Exemple :
labels:
- "traefik.enable=true"
- "traefik.http.routers.sandbox123.rule=Host(`sandbox123.preview.example.com`)"
- "traefik.http.routers.sandbox123.entrypoints=websecure"
- "traefik.http.services.sandbox123.loadbalancer.server.port=3000"
La Host rule route les requêtes vers sandbox123.preview.example.com vers ce container. loadbalancer.server.port indique le port interne sur lequel l’application écoute.
Chemin wake-on-request
Après l’arrêt d’un sandbox container par l’idle reaper, la première visite de la preview URL déclenche le wake flow :
- Le DNS résout vers Traefik ; il faut un wildcard DNS comme
*.preview.example.com - Traefik connaît la route de cette sandbox, mais le container est arrêté
- Le catch-all Traefik transmet la requête au wake handler du plan de contrôle
- Le plan de contrôle démarre le sandbox container et renvoie une warming page
- Quand le container est prêt, Traefik transfère les requêtes suivantes directement au container
Le catch-all doit avoir une priorité plus basse que tous les routers de sandbox :
labels:
- "traefik.http.routers.catch-all.rule=HostRegexp(`{subdomain:[a-z0-9-]+}.preview.example.com`)"
- "traefik.http.routers.catch-all.priority=1"
- "traefik.http.routers.catch-all.service=wake-service"
Les requêtes qui ne correspondent pas à une route de sandbox active tombent sur le catch-all, et le plan de contrôle gère le réveil.
Frontière de sécurité — permissions du Docker socket
Monter le Docker socket revient à donner au plan de contrôle un pouvoir proche du root host. C’est le compromis de sécurité de cette architecture : bon pour une équipe interne et des utilisateurs de confiance, pas pour du code non fiable.
Risques du Docker socket
La documentation Docker rappelle que le daemon a une surface d’attaque. Si l’API Docker est exposée de manière non sécurisée, un utilisateur distant non-root peut obtenir un accès root au host. Un container avec /var/run/docker.sock monté peut utiliser Docker CLI pour créer, modifier et supprimer des containers. Il peut aussi atteindre le système de fichiers et le réseau du host via les containers qu’il crée.
Cela implique :
- Le container de plan de contrôle possède des permissions élevées sur le host
- Il ne faut pas mélanger plan de contrôle et workloads non fiables sur le même host
- Le code dans les sandbox containers peut affecter indirectement le host s’il peut influencer le plan de contrôle
Limite pour les scénarios non fiables
Docker single-host + plan de contrôle Go convient à :
- Des environnements de preview pour membres d’équipe interne
- Des coding playgrounds pour utilisateurs de confiance
- Des environnements de validation internes pour AI app builders ou agent platforms
Il ne convient pas à :
- L’exécution de code arbitraire d’inconnus externes
- L’exécution production d’autonomous agents quand le host n’est pas fiable
- Des plateformes multi-tenant exigeant une forte isolation
Si la frontière de confiance passe de “équipe interne” à “utilisateurs externes”, passez aux Docker Sandboxes officiels ou à des microVM de type Firecracker. Docker Sandboxes ajoute isolation par hypervisor, réseau séparé, Docker daemon indépendant, système de fichiers indépendant et isolation des credentials. Chaque sandbox est une microVM complète, pas un container partageant le Docker daemon du host.
Checklist de hardening production
Avant la production, ajoutez ces frontières :
- Isolation réseau : plan de contrôle et sandbox containers tournent sur des réseaux dédiés, pas sur le réseau métier
- Authentification API : les quick starts locaux peuvent être sans auth ; la production exige token ou autre mécanisme d’authentification
- Surface minimale : exposez les preview URL via Traefik, jamais le port de l’API Docker
- TLS : les preview URL doivent utiliser un certificat wildcard TLS, pas du HTTP en clair
- Logs et monitoring : enregistrez les requêtes API du plan de contrôle et les événements de cycle de vie des containers, puis alertez
Pour une frontière plus forte, comparez gVisor, Firecracker et Kubernetes dans une architecture de sandbox pour AI agents.
Limites de ressources — memory / CPU / PIDs
Les containers Docker n’ont pas de contraintes de ressources par défaut. Sans limite, un sandbox container peut consommer la RAM et le CPU du host et perturber les autres sandboxes comme les processus host. Un environnement de preview multi-tenant a besoin de limites dures par container.
Comportement par défaut de Docker
La documentation Docker explique que les containers peuvent utiliser les ressources du host selon ce que permet le scheduler du noyau. Sans --memory ou --cpus explicite, un container peut prendre les ressources disponibles.
Limite mémoire dure
--memory définit la mémoire maximale disponible pour le container. Exemple :
docker run --memory="512m" --memory-swap="512m" sandbox-image
--memory-swap définit la limite mémoire + swap. Si --memory-swap est égal à --memory, le container n’utilise pas de swap.
Si le container dépasse sa limite mémoire, l’OOM killer peut terminer des processus du container. Un OOM au niveau host peut aussi toucher d’autres containers et processus host.
Limite de part CPU
--cpus définit la quantité de CPU disponible pour un container. Exemple :
docker run --cpus="0.5" sandbox-image
Le container peut utiliser au maximum 0,5 CPU. Quand plusieurs sandboxes tournent en parallèle, cette limite empêche un container de monopoliser toute la capacité de calcul.
Limite du nombre de processus
--pids-limit aide à éviter les fork bombs. Exemple :
docker run --pids-limit=100 sandbox-image
Le container peut créer au maximum 100 processus. Au-delà, fork() échoue.
Exemple de configuration Compose
Avec Docker Compose, configurez les limites dans deploy.resources.limits :
services:
sandbox:
image: sandbox-image
deploy:
resources:
limits:
cpus: "0.5"
memory: 512M
pids: 100
deploy.resources de Compose s’applique en mode Docker Swarm. Sur un host Docker unique, passez --memory, --cpus et --pids-limit manuellement, ou lancez docker-compose --compatibility.
Le plan de contrôle devrait injecter ces paramètres lors de la création des sandbox containers, plutôt que dépendre d’une configuration manuelle par l’utilisateur.
Exploitation — cache d’images et limites Docker Hub
Quand beaucoup de sandboxes sont créés et détruits fréquemment, les image pulls deviennent un goulot. Docker Hub a des pull rate limits et des abuse rate limits, avec des règles qui varient selon le type de compte et le plan. En production, il ne faut pas laisser chaque démarrage de sandbox dépendre directement du Docker Hub public.
Limites Docker Hub
La documentation Docker indique que les utilisateurs anonymes, authentifiés et les comptes d’équipe ont des politiques de pull différentes. Une fois la limite dépassée, les requêtes de pull sont rejetées. Les chiffres changent avec les politiques ; consultez Docker Hub usage and limits au lieu de les figer.
Dans un scénario multi-sandbox, cela signifie :
- La création fréquente de sandboxes peut tirer une image à chaque démarrage
- Après l’arrêt par idle reaper, un redémarrage peut nécessiter l’image à nouveau
- Plusieurs sandboxes peuvent tirer la même image plusieurs fois
Préchauffage d’images et stratégie de cache
La production a besoin de ces mesures.
Préchauffage d’images : tirez les images courantes localement avant de démarrer le plan de contrôle. Cela réduit l’attente lors du démarrage d’une sandbox.
Registry privé : poussez les images courantes dans un registry privé comme Harbor, AWS ECR ou Google Artifact Registry. Le plan de contrôle tire depuis ce registry privé au lieu de Docker Hub.
Login Docker Hub : si vous devez tirer depuis Docker Hub, utilisez un compte authentifié pour obtenir le quota adapté. Docker recommande de se connecter en production plutôt que de dépendre des pulls anonymes.
Cache d’images : le Docker daemon met déjà en cache les layers tirés. Si les sandbox containers sont souvent supprimés et recréés, évitez que les jobs de nettoyage suppriment trop agressivement les layers utiles.
Accélération de registry interne
Si le host est dans un réseau privé, configurez des mirrors ou proxies de registry pour les timeouts de pull Docker. Traitez ce point comme une partie de la plateforme, pas comme un correctif après la première panne.
Checklist de dépannage — preview URL inaccessible
Quand une preview URL ne s’ouvre pas, vérifiez ces cinq points dans l’ordre.
1. Le DNS pointe-t-il vers Traefik ?
Vérifiez l’enregistrement wildcard DNS. Le A record ou CNAME de *.preview.example.com doit pointer vers l’IP du host qui exécute Traefik.
Utilisez dig ou nslookup :
dig sandbox123.preview.example.com
L’IP retournée doit être celle du host Traefik, pas une autre adresse.
2. Traefik a-t-il découvert les labels du container ?
Vérifiez la configuration du Docker provider Traefik et les labels du container.
Utilisez le dashboard Traefik ou les logs :
docker logs traefik-container | grep "sandbox123"
Les logs Traefik doivent montrer la route de sandbox123. Sinon, vérifiez :
- La présence du label
traefik.enable=true - La configuration correcte de
exposedByDefault: false - Le montage correct du Docker socket dans Traefik
3. Le container est-il démarré ?
Vérifiez l’état du sandbox container.
Utilisez docker ps :
docker ps | grep sandbox123
Si le container est arrêté, l’idle reaper l’a peut-être stoppé, ou le wake path n’a pas réussi à le redémarrer. Accéder à la preview URL devrait faire démarrer le container par le wake handler et afficher une warming page. Si ce chemin échoue, vérifiez les logs du plan de contrôle.
4. Sur quelle adresse l’application écoute-t-elle ?
Vérifiez l’adresse et le port d’écoute dans le container.
Entrez dans le container et inspectez les ports :
docker exec sandbox123 netstat -tuln
L’application doit écouter sur 0.0.0.0:3000, pas seulement sur 127.0.0.1:3000. La documentation Docker indique que les ports liés à 127.0.0.1 ou ::1 ne sont accessibles que depuis le Docker host ; les requêtes externes n’arrivent donc pas.
Si l’application écoute seulement localhost, changez sa configuration ou utilisez un mode réseau adapté.
5. Le port binding correspond-il ?
Comparez le port de service Traefik avec le port réel de l’application.
Le label Traefik peut dire :
- "traefik.http.services.sandbox123.loadbalancer.server.port=3000"
L’application dans le container doit écouter sur le port 3000. Si Traefik pointe vers 3000 mais que l’application écoute sur 8080, les requêtes échouent.
Quand les ports ne correspondent pas, corrigez les labels Traefik ou la configuration de l’application.
Conclusion
Un host Docker unique avec un plan de contrôle Go peut porter un environnement de preview auto-hébergé : chaque sandbox a sa preview URL, les ressources sont limitées et le compromis de sécurité est explicite. Le périmètre reste clair : équipes internes, utilisateurs de confiance, petite concurrence. Si la frontière de confiance s’ouvre à des inconnus ou si la concurrence dépasse un host, passez aux microVM ou à Kubernetes.
Les modules essentiels restent lisibles : le tableau de décision fixe le périmètre ; le plan de contrôle, Traefik, SQLite et les reapers expliquent les pièces mobiles ; les preview URL reposent sur les Host rules Traefik et les Docker labels ; la sécurité traite le Docker socket comme un pouvoir host ; les limites de ressources sont la base du multi-tenant ; le cache d’images réduit le risque Docker Hub ; la checklist de dépannage donne un chemin quand les preview URL cassent.
Étapes suivantes :
- Previews pour petite équipe interne : démarrez avec Docker sur un host et un plan de contrôle Go, puis mesurez la densité de ressources
- Utilisateurs externes ou workloads à risque : passez à Docker Sandboxes, Firecracker ou une autre frontière microVM
- Self-hosted CI runner : lisez le guide GitHub Actions self-hosted runner pour compléter l’infrastructure privée
- Applications dans l’environnement de preview : utilisez le guide Next.js Docker self-hosting pour faire tourner l’app dans la sandbox
Construire un MVP de Dev Sandbox auto-hébergé
Passer d'un host Docker unique à un environnement de preview interne avec limites de ressources et contrôle d'accès.
⏱️ Estimated time: 4 hr
- 1
Step 1: Choisir le modèle d'isolation
Utilisez Docker sur un host unique pour une équipe de confiance et de petites charges de preview. Pour des utilisateurs inconnus ou du code non fiable, choisissez microVM, hosts séparés ou Kubernetes. - 2
Step 2: Préparer le plan de contrôle
Exécutez un petit service Go qui possède les métadonnées de sandbox, les opérations de cycle de vie, les reapers et la logique wake-on-request. - 3
Step 3: Configurer la discovery Traefik
Activez le Docker provider avec `exposedByDefault: false`, puis ajoutez des labels uniquement aux containers sandbox qui doivent recevoir du trafic. - 4
Step 4: Attribuer des preview URL stables
Utilisez un wildcard DNS comme `*.preview.example.com`, puis routez chaque host `{sandbox_id}.preview.example.com` vers le port du container qui sert l'application. - 5
Step 5: Persister les workspaces
Stockez chaque sandbox dans `SANDBOXED_DATA_DIR/workspaces/` ou un répertoire host équivalent afin que `docker stop` ne supprime pas les fichiers utilisateur. - 6
Step 6: Ajouter des limites de ressources
Définissez des limites memory, CPU et PIDs sur chaque sandbox. Un build qui part en boucle ne doit pas affamer le host. - 7
Step 7: Sécuriser les points d'entrée de production
N'exposez pas l'API Docker. Ajoutez authentification API, TLS, contrôle d'accès des preview links, séparation réseau et audit logs. - 8
Step 8: Planifier les images et le registry
Pré-téléchargez les images fréquentes, connectez-vous à Docker Hub si nécessaire et utilisez un registry privé ou un cache quand les sandboxes sont créés souvent.
FAQ
Quelle est la différence entre un Dev Sandbox et Docker Compose ?
Pourquoi ne pas partir directement sur Kubernetes ?
L'isolation Docker permet-elle d'exécuter du code arbitraire d'inconnus ?
Une preview URL doit-elle forcément être en HTTPS ?
Les fichiers disparaissent-ils après un idle stop ?
Les rate limits de Docker Hub peuvent-ils poser problème ?
14 min de lecture · Publié le: 5 juin 2026 · Mis à jour le: 14 juil. 2026
Guide pratique Docker
Vous lisez le premier article de cette série. Continuez avec le suivant ou ouvrez le hub de la série pour voir tout le parcours.
Précédent
Vous êtes au début de cette série.
Suivant
C’est le dernier article publié dans cette série pour le moment.

Commentaires
Connectez-vous avec GitHub pour laisser un commentaire