Many MCP servers ship as Docker images — it is language-agnostic and avoids "works on my machine" runtime issues. Here is exactly how a client launches a Dockerised server, with a real, working example.
Why Docker
- No local runtime needed — no Node or Python version juggling.
- Isolation — the server runs in a container, not your host.
- Reproducible — the same image everywhere, including CI and self-hosted setups.
The trade-off: the container must talk to the client over stdio, so you run it with -i (interactive) and --rm (clean up on exit).
Working example — GitHub server
The official GitHub MCP server is distributed as ghcr.io/github/github-mcp-server:
{
"mcpServers": {
"github": {
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"],
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxx" }
}
}
}
The client runs this docker run command on demand. -e GITHUB_PERSONAL_ACCESS_TOKEN forwards the env var into the container.
Passing files (volumes)
If the server needs local files (e.g. a filesystem or SQLite server), mount a volume:
"args": ["run","-i","--rm","-v","/Users/you/data:/data","some/mcp-image","--db","/data/app.db"]
The host path is before the colon, the container path after.
Verify
Restart the client and check the tools panel. Ask the agent to use a tool from the server.
Common problems
Cannot connect to the Docker daemon— Docker Desktop must be running before the client launches.failed to pull image— the image is private or the name is wrong; for GHCR public images, an expired login can block it (docker logout ghcr.io).- Env var empty inside container — you listed
-e VARbut did not set it inenv(or your shell). - Volume not found — use absolute host paths.
Going further
Deploying a server as a long-running service? See deploy an MCP server with Docker and Cloudflare and running MCP servers with Docker. Building one to containerise? Start with build your first MCP server.