Skip to content

no-docker-socket-mount

Bind-mounting /var/run/docker.sock into a Compose service hands the container root on the host. Safer alternatives for tools that need the Docker API.

On this page

Mounting /var/run/docker.sock into a container is the standard trick for anything that needs to talk to Docker: CI runners, reverse proxies that watch containers, and increasingly AI-agent tooling like MCP gateways that launch tool containers on demand. It is also equivalent to giving that container root on the host, because the Docker API can start privileged containers, mount any host path, and read every volume. This rule flags any service whose volumes bind-mount the Docker socket, in either the short or long syntax.

What the rule catches

compose.yaml — raw Docker socket bind mount
services:
  mcp-gateway:
    image: docker/mcp-gateway:0.9.0
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

Scanning this file reports:

✖ ERROR [docker-doctor/no-docker-socket-mount]
  Service 'mcp-gateway' bind-mounts the Docker socket. Anything running in this container can control the Docker daemon: start privileged containers, read every volume, and escape to the host.

Why it matters

The Docker daemon runs as root and its API has no notion of partial trust. Any client can do anything, including docker run --privileged -v /:/host, so a compromised process in a socket-mounted container escapes to the host in one API call. Agent stacks raise the stakes: an MCP gateway or agent runtime executes model-directed actions, so prompt injection anywhere in the toolchain becomes a path to that socket.

How to fix it

If the service genuinely needs the Docker API (agent tooling like MCP gateways often does), prefer use_api_socket: true or a filtering socket proxy over a raw bind mount of /var/run/docker.sock.

compose.yaml — scoped API access via use_api_socket
services:
  mcp-gateway:
    image: docker/mcp-gateway:0.9.0
    # Compose provisions scoped Docker API credentials for this service
    use_api_socket: true

If the service genuinely needs the Docker API, use a mechanism that limits what a compromised container can do:

  • use_api_socket: true (Compose ≥ 2.36): Compose mounts the API socket together with scoped credentials. Docker's own compose-for-agents examples use this for MCP gateways.
  • A filtering socket proxy: exposes only the API endpoints the client needs, such as read-only container listing.

Mounting the socket :ro does not help. Writes go through the connected socket, not the file, so a read-only mount still allows every API call.

Rule details

  • Rule keydocker-doctor/no-docker-socket-mount
  • Category — Compose
  • Default severityerror
  • Applies to — Docker Compose files

Explain this rule from the CLI:

npx @docker-doctor/cli@latest rules explain docker-doctor/no-docker-socket-mount

Change its severity — or turn it off — in your config file:

// docker-doctor.config.ts
export default {
  rules: {
    "docker-doctor/no-docker-socket-mount": "off",
  },
};

Severity affects the health score: error findings cost more points than warning, and info costs the least.