Skip to main content
Glama
zshureih
by zshureih

docker-mcp

An MCP (Model Context Protocol) server that creates Docker containers by talking directly to the Docker Engine API over /var/run/docker.sock.

Why this exists

It's the sibling project to unraid-mcp, which wraps Unraid's official GraphQL API. That API has no container-creation mutation — Unraid's own "Add Container" feature is a separate webGUI/dockerMan subsystem, not part of the official API. docker-mcp fills that one gap by talking to the Docker Engine directly, using the official docker Python SDK (never shelling out to docker run — every parameter is a typed field in a structured API payload, not a shell string).

It is deliberately not a fork or subfolder of unraid-mcp, and deliberately narrow in scope: exactly two tools, pull_image and create_container. Once a container exists — regardless of how it was created — unraid-mcp's existing docker/start, stop, remove_container, etc. already manage it by ID against the same Docker daemon. This project does not duplicate that lifecycle surface.

Related MCP server: Docker MCP Server

Why a separate server instead of adding this to unraid-mcp

Controlling the Docker Engine is root-equivalent access to the host. Bolting that onto unraid-mcp (which is a large, LLM-driven tool surface across 19 domains) would mean every one of those 178 operations shares a blast radius with "can create arbitrary containers." Splitting it out means only this small, narrowly-scoped server gets the Docker socket mount — unraid-mcp stays exactly as sensitive as its GraphQL API and nothing more.

Security posture — read this

  • privileged and host PID-namespace sharing are not supported at all — there is no parameter for them anywhere, on any code path.

  • network="host" and bind-mounting the Docker socket, host root (/), /etc, /proc, /sys, /var/lib/docker, /root, or /boot are rejected before any Docker Engine call is made (see docker_mcp/core/validation.py).

  • This validation is a guardrail against mistakes, not a security boundary. Anyone who can call create_container already has root-equivalent control of the host via the Docker Engine — the same daemon would happily do any of the above if asked directly with the Docker CLI. Don't expose this server to anyone/anything you wouldn't hand a root shell.

  • create_container requires confirm=True (or interactive elicitation) — same pattern as unraid-mcp's destructive-action gating.

  • HTTP transport requires a bearer token by default (auto-generated into ~/.docker-mcp/.env on first startup) and refuses to bind an unauthenticated endpoint to a non-loopback address unless you explicitly set DOCKER_MCP_TRUST_PROXY=true behind a gateway that enforces auth itself.

  • The entrypoint.sh docker.sock GID-matching trick (joining a group that matches the socket's GID instead of running fully as root) is best-effort hardening that mostly helps on Debian-style root:docker hosts. On Unraid the socket is commonly root:root, in which case there's no non-root group to join and the entrypoint falls back to running as root with a printed warning — Docker Engine access is root-equivalent either way, so this is not pretending to be a real isolation boundary.

Tools

pull_image(image, tag="latest", platform=None)

Pulls an image onto the Docker host. Not gated — download-only, no host mutation.

create_container(image, name=None, environment=None, ports=None, volumes=None, network=None, restart_policy=None, labels=None, command=None, working_dir=None, cap_add=None, mem_limit=None, start=True, confirm=False)

Creates (and by default starts) a container. Requires the image to already be present locally — call pull_image first if needed.

create_container(
    image="lscr.io/linuxserver/plex:latest",
    name="plex",
    environment={"PUID": "1000", "PGID": "1000", "TZ": "America/New_York"},
    ports={"32400/tcp": 32400},
    volumes={"/mnt/user/appdata/plex": {"bind": "/config", "mode": "rw"},
             "/mnt/user/media": {"bind": "/media", "mode": "ro"}},
    restart_policy={"Name": "unless-stopped"},
    confirm=True,
)

Running it

cp .env.example ~/.docker-mcp/.env   # edit as needed
docker compose up -d

docker-compose.yaml pulls the prebuilt image from ghcr.io/zshureih/docker-mcp, published by .github/workflows/docker-publish.yml on every push to main. To build locally instead (e.g. while developing), replace the image: line with build: ..

The bearer token is auto-generated into ~/.docker-mcp/.env on first HTTP startup if not already set — check the container logs for it.

Making it reachable from other devices on your LAN

By default the published port is bound to 127.0.0.1 on the Docker host — nothing else on your network can reach it, even with the token. To expose it to other LAN devices, set DOCKER_MCP_BIND_HOST in a project-root .env file (Docker Compose's own dotenv mechanism, which it reads when parsing docker-compose.yaml — this is a different file from ~/.docker-mcp/.env, which is the app's own credentials file loaded inside the container and has no effect on Compose's port-mapping substitution):

echo "DOCKER_MCP_BIND_HOST=192.168.0.174" >> .env   # your Unraid host's LAN IP
docker compose up -d

Keep bearer-token auth enabled (DOCKER_MCP_DISABLE_HTTP_AUTH=false, the default) when doing this — otherwise every device on your LAN could create and control containers on your Unraid box with no authentication at all. Only set DOCKER_MCP_DISABLE_HTTP_AUTH=true if a reverse proxy genuinely sits in front of this port and enforces auth itself (in which case also set DOCKER_MCP_TRUST_PROXY=true); the server refuses to start otherwise once it detects a non-loopback bind with auth disabled.

Development

uv sync --group dev
uv run pytest
uv run ruff check docker_mcp/
uv run ty check docker_mcp/
A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/zshureih/docker-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server