How to run mini-me in a container
mm dockerinit writes a Dockerfile and a compose.yaml in the current directory. The image holds the latest released mm and the tools of its bash tool; compose mounts your project and runs the agent as you, not as root.
For Docker's microVM sandboxes rather than a plain container, see how to run mini-me in a Docker Sandbox.
Before you start
- Docker with Compose.
- An agent file in the project. If you have none, run
mm initfirst (see create an agent). - A model server on your machine that the container can reach: see Reach the model.
Write the files
In your project's directory:
mm dockerinit
The service is named after acp.name in agent.yaml, or mm if there is none. To choose, use mm dockerinit --name bob. The rest of this guide calls it bob.
If a file already exists, mm asks Overwrite Dockerfile?, and no is the default. With --yes, or when the input ends, nothing at all is written.
A project with a .mm folder
When the agent is .mm/agent.yaml (made with mm init --project yes, see keep a project's mini-me files in a .mm folder), mm dockerinit finds it with no flag — it looks for agent.yaml, then .mm/agent.yaml, as mm does — and names the service after it. compose.yaml then:
- mounts
.mm/read-only over the project: the agent cannot change its own settings, skills or hooks; - mounts the folders mm writes in — the agent file's
sessions.dirandtrace.dir, when they are on and under.mm/— writable again, and creates them now if they do not exist (Docker would create them as root, and the agent never runs as root); - starts
mm tuiwith no file: mm finds.mm/agent.yamlfrom the project.
volumes:
- .:${PWD:-/workspace}
- ./.mm:${PWD:-/workspace}/.mm:ro
- ./.mm/sessions:${PWD:-/workspace}/.mm/sessions # sessions.dir
Anything else written under .mm/ — a hook that keeps a log there — needs a line of its own. After turning sessions or the trace on or off, run mm dockerinit again (answer yes to replace compose.yaml).
Run the agent
Either keep a container running, which also serves an editor:
docker compose up -d --wait
docker compose exec bob mm tui agent.yaml
Or run one session, in a container that goes away with it:
docker compose run --rm bob mm tui agent.yaml
Both open the single-window mode (mm tui) and can be used at the same time. The first run builds the image.
Connect an editor (ACP)
Start the container with docker compose up -d --wait, then give your editor this command, with the project's absolute path:
docker exec -i bob-box mm --acp --config /path/to/project/agent.yaml
The project is mounted at the same path as on your machine, so the paths the editor sends mean the same thing inside the container. For a .mm project, docker exec -i bob-box mm --acp is enough: the container starts in the project, where mm finds .mm/agent.yaml.
Reach the model
From the container, localhost is the container. dmr, llmman and ollama fall back on host.docker.internal by themselves when their default address does not answer, as long as the agent file sets no baseUrl. The compose file makes that name known on Linux too.
llamacpphas no such fallback: setbaseUrl: http://host.docker.internal:8080/v1.- An agent file with a
baseUrlonlocalhostor127.0.0.1: replace the host withhost.docker.internal, or add afallback. - A server on Linux that only listens on
127.0.0.1: make it listen on an address the container can reach.host.docker.internalis then the host's gateway, not its loopback.
Update to the latest release
docker compose build
docker compose up -d --wait
Docker reads the release's SHA256SUMS at each build: when it has changed, the steps that install mm run again.
Build for both architectures
docker compose builds for your machine's architecture. To publish an image for linux/amd64 and linux/arm64:
docker buildx build --platform linux/amd64,linux/arm64 -t <registry>/mm-bob:latest --push .
Building for the other architecture needs emulation (QEMU, included in Docker Desktop). Without it, the build stops with exec format error.
An image built this way, outside compose, gives its mm account the uid and gid 1000. Whoever runs it with other numbers gets a user with no name in the container: add --build-arg MM_UID=… --build-arg MM_GID=… to build it for them.
Use the files on another machine
compose.yaml records the uid and gid of the machine that ran mm dockerinit. The container runs as that user, so that the files the agent creates belong to you, and the image's mm account is built with the same numbers, so that every program in the container knows who it runs as — whoami, the shell's prompt, ssh. On a machine where yours differ, set them, then rebuild the image:
export MM_UID=$(id -u) MM_GID=$(id -g)
docker compose up -d --build
Without the rebuild, the container runs as your uid while the image's account keeps the old one: the shell's prompt then reads I have no name! and whoami fails.
Files written by mm dockerinit before v1.1.0 always built the account with uid 1000 — on a Mac, whose user is uid 501, the shell said I have no name!. Run mm dockerinit again (answer yes to replace both files), then docker compose up -d --build.
git in the container still needs an identity to commit: the account has a name, but git does not make one up from it. Set user.name and user.email in the project (git config user.name …), or pass GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL to the container.
What the container protects
The agent does not run as root, but it can still change and delete everything in the mounted project, and it has network access. Keep the project under version control, and use yolo: false if you want to approve each command: see confirm tool calls.
All the flags are in the CLI reference.
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 |
|