Faire tourner mini-me dans un Docker Sandbox
Ce guide montre comment exécuter mm dans un Docker Sandbox, pour que chaque commande lancée par le modèle et chaque fichier qu'il modifie le soient dans un conteneur, sur votre projet monté. Il couvre les deux usages : le mode fenêtre dans votre terminal, et depuis un éditeur via l'Agent Client Protocol. Il suppose Docker Desktop avec la commande sbx, et un serveur de modèles (Docker Model Runner ou llama-server) qui tourne sur votre machine.
Ce sont les kits v2 (
spec.yaml). Les deux mêmes kits existent aussi pour la spécification de kit v3, sousdocker-sbx-v3/: voir Faire tourner mini-me avec les kits sandbox v3.
Tout est sous docker-sbx/ dans le dépôt :
| Élément | Ce que c'est |
|---|---|
template/Dockerfile |
Le template : l'image shell de Docker Sandboxes avec mm compilé depuis ce dépôt, plus les deux points d'entrée ci-dessous. |
kits/mm-tui/spec.yaml |
Un kit sandbox : sbx run dessus ouvre le mode fenêtre de mm sur l'espace de travail. |
kits/mm-acp/spec.yaml |
Un kit sandbox pour un éditeur : créé une fois avec sbx create, l'éditeur y lance ensuite mm -acp. |
build.sh |
Construit l'image du template, k33g/mm-sandbox:<version> ; PUSH=1 la construit pour linux/amd64 et linux/arm64 et la pousse. |
sync-kits.sh, push-kits.sh |
Alignent les kits sur une image, et les publient sur Docker Hub comme artefacts OCI de kit. |
Utiliser les kits publiés
Chaque release publie l'image et les deux kits sur Docker Hub à la version de mm — k33g/mm-sandbox:0.2.1, k33g/mm-tui:0.2.1, k33g/mm-acp:0.2.1 — le chemin le plus court ne demande donc aucune construction. Docker Hub est une source de kits autorisée par défaut (sbx settings get kit.allowedSources montre docker.io/), et une référence avec un / mais sans hôte de registre est lue comme docker.io/… :
cd /chemin/de/votre/projet
sbx run k33g/mm-tui:0.2.1 . -- agent.dmr.yaml
pour le mode fenêtre, et pour un éditeur :
sbx create --name mm-acp k33g/mm-acp:0.2.1 . --kit-arg config=agent.dmr.yaml
puis la déclaration dans l'éditeur de l'étape 3 ci-dessous. Pas de --pull never : le kit nomme k33g/mm-sandbox:0.2.1 et sbx la télécharge. sbx kit inspect k33g/mm-tui:0.2.1 montre ce qu'un kit déclare avant de le lancer. Les étapes qui suivent construisent la même chose en local, pour un mm en cours de travail.
Étapes
1. Construire le template
Depuis la racine du dépôt :
./docker-sbx/build.sh
Cela lit le tag de mm dans release.env (v0.2.1) et construit k33g/mm-sandbox:0.2.1 : le tag de l'image est la version sans le v, comme les binaires de release, et le mm à l'intérieur est estampillé avec le tag — mm --version est exécuté dans l'image comme preuve. Le script réécrit ensuite la valeur par défaut de l'argument tag des kits à 0.2.1, pour que kits et image avancent ensemble. ./docker-sbx/build.sh v0.1.5 construit une autre version ; une image antérieure reste joignable avec --kit-arg tag=0.1.4.
L'image est dans votre store d'images Docker local : chaque sbx run ou sbx create sur ces kits prend --pull never tant qu'elle n'est pas poussée (docker push k33g/mm-sandbox:0.2.1), sinon sbx tente de la télécharger et échoue. Si sbx tourne sur une autre machine, EXPORT=1 ./docker-sbx/build.sh écrit aussi tmp/mm-sandbox-0.2.1.tar, à charger là-bas avec sbx template load.
2. Mode fenêtre dans le terminal (kit mm-tui)
Depuis le projet sur lequel mm doit travailler :
sbx run --pull never ./docker-sbx/kits/mm-tui . -- agent.dmr.yaml
La première fois, sbx crée le sandbox, monte le répertoire courant comme espace de travail et s'y attache ; puis il lance le point d'entrée du kit avec ce qui suit -- en arguments — ici mm -tui agent.dmr.yaml, dans l'espace de travail. N'importe quel drapeau de mm passe de la même façon : -- -config autre.yaml.
Sans rien après --, mm lit l'argument config du kit, puis ./agent.yaml dans l'espace de travail, puis ses valeurs par défaut :
sbx run --pull never ./docker-sbx/kits/mm-tui . --kit-arg config=agent.dmr.yaml
--kit-arg |
Défaut | Effet |
|---|---|---|
config=<chemin> |
vide | Le fichier de configuration, comme AGENT_CONFIG de mm : relatif à l'espace de travail, ou absolu dans le sandbox. |
tag=<version> |
la dernière version construite (0.2.1) |
L'image k33g/mm-sandbox:<version> dont le sandbox est fait. |
Le sandbox garde son nom (mm-tui-<répertoire> sauf --name) ; sbx run --name <nom> s'y rattache plus tard. À l'intérieur, la fenêtre est celle décrite dans Utiliser le mode fenêtre. Les sessions, quand sessions.enabled est actif, sont écrites sous .mm/sessions dans l'espace de travail — c'est votre répertoire hôte, elles survivent donc au sandbox.
3. Depuis un éditeur (kit mm-acp)
Un éditeur parle à mm -acp sur l'entrée et la sortie standard brutes de l'agent. sbx run ne peut pas porter cela : il alloue toujours un terminal. Le sandbox est donc créé une fois sans s'y attacher, et l'éditeur y lance mm avec sbx exec -i, qui transmet stdin et stdout tels quels.
-
Depuis le projet que l'éditeur ouvrira, créez le sandbox avec le fichier de configuration intégré (
.est l'espace de travail, sbx le rend absolu ; le chemin du kit doit être explicite :./,../ou absolu) :cd /chemin/de/votre/projet sbx create --pull never --name mm-acp /chemin/de/mini-me/docker-sbx/kits/mm-acp . \ --kit-arg config=agent.dmr.yamlUn chemin d'espace de travail qui n'existe pas sur votre machine fait demander à sbx « The selected workspace does not exist. Would you like to create it? » — répondez
Net corrigez le chemin.--kit-arg configdevient l'AGENT_CONFIGdu conteneur, relatif à l'espace de travail parce que c'est là quesbx execdémarremm. L'espace de travail est fixé à la création : un sandbox par projet, chacun avec son--name. -
Déclarez-le dans l'éditeur. Dans le
settings.jsonde Zed :{ "agent_servers": { "mini-me (sandbox)": { "type": "custom", "command": "sbx", "args": ["exec", "-i", "mm-acp", "mm", "-acp"] } } }Par rapport à la configuration côté hôte, la commande est
sbxet aucunenvn'est nécessaire :AGENT_CONFIGest déjà dans le conteneur. Si l'éditeur ne trouve passbx, mettez le chemin absolu donné parwhich sbxdans"command". -
Ouvrez le panneau agent et choisissez mini-me (sandbox). L'éditeur lance
mm -acpdans le sandbox à chaque conversation ;sbx execdémarre d'abord le sandbox s'il est arrêté. Appels d'outils, dialogues de permission, mentions@fichieret menu des commandes fonctionnent comme sur l'hôte — la différence est l'endroit où les commandes s'exécutent.
S'attacher à ce sandbox avec sbx run --name mm-acp ne lance pas mm : son point d'entrée affiche le câblage ci-dessus avec le vrai nom et les vrais chemins du sandbox, puis ouvre un shell à l'intérieur. sbx exec -it mm-acp bash est le chemin le plus court vers ce shell.
Le serveur de modèles reste sur l'hôte
Dans un sandbox, localhost est le sandbox lui-même. Votre serveur de modèles continue de tourner sur votre machine et se joint par host.docker.internal, que le proxy du sandbox fait pointer vers le localhost de l'hôte.
- Docker Model Runner — rien à changer :
agent.dmr.yamla déjàfallback: http://host.docker.internal:12434/engines/v1, etmmbascule dessus quandlocalhost:12434ne répond pas (la bannière dit quelle URL a gagné). - llama-server —
agent.llamacpp.yamln'a pas de fallback. Soit vous changez sonbaseUrlenhttp://host.docker.internal:8080/v1, soit vous passez--env AGENT_BASE_URL=http://host.docker.internal:8080/v1àsbx run/sbx create(voir Faire tourner sur llama.cpp).
Les deux kits autorisent les ports 12434 et 8080 de l'hôte dans la politique réseau du sandbox. Pour un autre port : sbx policy allow network host.docker.internal:<port>.
Publier une version
La publication est une étape manuelle, depuis une machine avec Docker Desktop (buildx et la CLI sbx) ; le workflow Release ne construit que les binaires. Un script construit l'image pour linux/amd64 et linux/arm64, la pousse, puis valide et pousse les deux kits, le tout au tag de mm :
export DOCKER_HANDLE=k33g # le compte Docker Hub, aussi propriétaire de l'image
export DOCKER_PAT=dckr_pat_… # un jeton d'accès en lecture/écriture
./docker-sbx/publish.sh # TAG depuis release.env : v0.2.1 → k33g/mm-sandbox:0.2.1, k33g/mm-tui:0.2.1, k33g/mm-acp:0.2.1
Avec les deux variables, le script se connecte avec elles et se déconnecte à la fin ; sans elles, il réutilise votre docker login existant. Ses deux moitiés se lancent seules : PUSH=1 ./docker-sbx/build.sh v0.2.1 (l'image) et ./docker-sbx/push-kits.sh v0.2.1 (les kits, SBX=/chemin/vers/sbx si la CLI n'est pas sur le PATH). Les deux appellent d'abord sync-kits.sh, qui réécrit version, le tag par défaut et le propriétaire de l'image des kits, de sorte qu'un kit publié nomme toujours l'image poussée avec lui — commitez ensuite les deux spec.yaml. sbx kit push parle directement au registre et s'authentifie depuis le magasin d'identifiants Docker, sans démon sandbox. IMAGE_OWNER=<compte> publie sous un autre compte.
Serveurs MCP via la passerelle sbx (exemple : GitHub)
Dans un sandbox, mm ne parle pas lui-même aux serveurs MCP et ne détient aucun jeton. sbx démarre une passerelle MCP par sandbox, sur l'hôte. À la création du sandbox, il inscrit deux variables dans le conteneur : MCP_GATEWAY_URL (http://mcp-gateway.docker.internal/mcp) et MCP_SENTINEL_TOKEN_NAME, un substitut que le proxy du sandbox remplace par le vrai identifiant. Quand mm trouve MCP_GATEWAY_URL et mcp.enabled: true, il ajoute un serveur nommé sbx-gateway, dont les outils apparaissent sous la forme sbx-gateway_<outil>. Le kit n'a besoin d'aucune règle réseau pour cela, car le proxy route cet hôte lui-même.
-
Enregistrez une fois, sur l'hôte, le serveur officiel de GitHub via
docker-sbx/mcp/github-mcp.sh. Le script lanceghcr.io/github/github-mcp-serverdans Docker avec votre jeton. sbx l'exécute comme enfant de sandboxd, qui ne voit pas les variables de votre shell. Rangez donc le jeton une fois dans le trousseau macOS, sous le servicegithub-mcp. Le script accepte aussiGITHUB_PERSONAL_ACCESS_TOKEN,GITHUB_OAUTH_TOKENou unghconnecté. sbx l'exécute sur l'hôte, donc le jeton n'entre jamais dans le sandbox. Par défaut, il expose 25 outils en lecture seule, dontget_meetget_teams. Pour en avoir plus, définissezGITHUB_READ_ONLY=0et unGITHUB_TOOLSETSplus large dans l'environnement du script.security add-generic-password -U -a "$USER" -s github-mcp -w # demande le jeton sbx mcp rm github 2>/dev/null # un ancien "github" est le serveur ARCHIVÉ du catalogue sbx mcp add github-mm --command "$PWD/docker-sbx/mcp/github-mcp.sh" sbx mcp ls # github-mm doit être prêtN'utilisez pas le nom
githubseul. Le catalogue Docker MCP le résout en « GitHub (Archived) », l'ancien serveur npm, qui n'a pasget_meet propose d'autres outils. L'entréegithub-officialdu catalogue ne convient pas non plus en mode local. Là, une image du catalogue est lancée par un simpledocker run, sans environnement, donc sans jeton. -
Créez un nouveau sandbox avec ce serveur dans son ensemble fixe.
--static-mcpest une option desbx: elle se place avant--, car tout ce qui suit--va àmm. Elle ne s'applique qu'à la création, donc supprimez d'abord un ancien sandbox du même nom :cd /chemin/du/projet sbx rm mm-mcp-github 2>/dev/null sbx run --name mm-mcp-github --static-mcp github-mm k33g/mm-tui:<version> . -- agent.dmr.sbx.yaml -
La configuration doit seulement activer MCP.
demo/agent.dmr.sbx.yamlcontient :mcp: enabled: true permissions: ask discoveryTimeout: 10s servers: [] # mm ajoute la passerelle quand MCP_GATEWAY_URL est définiLa bannière liste alors
sbx-gateway_get_me,sbx-gateway_list_issues, etc. danstools:.
Une image de kit construite avant ce changement ne peut pas utiliser la passerelle. Elle ne découvre rien et affiche method "tools/list" is invalid during session initialization. La passerelle suit strictement le transport Streamable HTTP de MCP : elle exige d'abord initialize, puis le Mcp-Session-Id renvoyé sur chaque requête. L'ancien mm sautait les deux. C'était sans effet face à api.githubcopilot.com, mais bloquant ici. Reconstruisez et republiez le kit après la mise à jour.
Si la bannière ne liste aucun outil sbx-gateway_*, vérifiez l'enregistrement avec sbx mcp inspect github-mm, puis lisez le journal MCP de sbx, mcp/mcp.log dans son répertoire d'état. github-mcp: no token dans ce journal signifie que le script n'a trouvé aucun jeton : vérifiez l'entrée du trousseau avec security find-generic-password -s github-mcp. L'endpoint distant https://api.githubcopilot.com/mcp/ est une autre voie, mais seulement avec une OAuth App GitHub. GitHub ne propose pas l'enregistrement dynamique de client, donc en mode local sbx mcp add le refuse sans --client-id, même avec un en-tête Authorization.
Nommez le dépôt dans vos demandes, par exemple « liste les issues ouvertes de k33g/mon-depot ». Un petit modèle à qui l'on dit seulement « mon organisation » invente un propriétaire et un dépôt, et chaque appel revient en Not Found.
Variantes
- Une autre configuration pour une session d'éditeur. Ajoutez
"-e", "AGENT_CONFIG=agent.lsp.yaml"avant le nom du sandbox dans"args";sbx exec -eremplace la valeur intégrée pour cette exécution seulement. - Skills.
skillsDirest relatif au répertoire oùmmtourne, c'est-à-dire l'espace de travail dans les deux kits — la même règle que sur l'hôte. - Docker dans le sandbox. Construisez le template sur le shell Docker-in-Docker :
SHELL_TEMPLATE=docker/sandbox-templates:shell-docker ./docker-sbx/build.sh. - Lire les logs. En mode fenêtre ils sont à l'écran ; en ACP ils vont sur stderr, que Zed montre sous
dev: open acp logs. - Supprimer un sandbox.
sbx rm mm-acp. Le répertoire du projet est un montage et n'est pas touché.
Voir aussi
- Le format suivi par ces deux fichiers : la spécification des kits de Docker Sandboxes (
schemaVersion: "2"), livrée avec les sources desbx. - Les mêmes kits pour la spécification de kit v3 : Faire tourner mini-me avec les kits sandbox v3.
- Ce que
mm -acpexpose à l'éditeur : référence ACP. - Les drapeaux et variables d'environnement que
mmlit : référence de la ligne de commande.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
|