> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/microsoft/playwright-mcp/llms.txt
> Use this file to discover all available pages before exploring further.

# Docker Deployment

> Run Playwright MCP in Docker for isolated and production-ready deployments

Docker provides an isolated environment for running Playwright MCP, which is recommended for production deployments and security-sensitive scenarios.

<Note>
  The Docker implementation currently only supports headless Chromium.
</Note>

## Spawned Container Mode

In this mode, the MCP client spawns a new Docker container for each session.

```json theme={null}
{
  "mcpServers": {
    "playwright": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "--init",
        "--pull=always",
        "mcr.microsoft.com/playwright/mcp"
      ]
    }
  }
}
```

### Configuration Options

* `-i`: Interactive mode (required for STDIO communication)
* `--rm`: Automatically remove container when it exits
* `--init`: Use an init process to handle signals properly
* `--pull=always`: Always pull the latest image before running

## Long-Lived Service Mode

For better performance and resource management, you can run the container as a long-lived service instead of letting the MCP client spawn it.

### Starting the Service

```bash theme={null}
docker run -d -i --rm --init --pull=always \
  --entrypoint node \
  --name playwright \
  -p 8931:8931 \
  mcr.microsoft.com/playwright/mcp \
  cli.js --headless --browser chromium --no-sandbox --port 8931 --host 0.0.0.0
```

### Configuration

* `-d`: Run in detached mode
* `--name playwright`: Name the container for easier management
* `-p 8931:8931`: Map port 8931 to host
* `--host 0.0.0.0`: Bind to all interfaces inside the container
* `--no-sandbox`: Required in most Docker environments

### Client Configuration

Configure your MCP client to connect to the HTTP endpoint:

```json theme={null}
{
  "mcpServers": {
    "playwright": {
      "url": "http://localhost:8931/mcp"
    }
  }
}
```

The server will be accessible on host port **8931** and can be reached by any MCP client.

## Building Custom Docker Image

You can build the Docker image yourself for customization or local development.

### Clone and Build

```bash theme={null}
# Clone the repository
git clone https://github.com/microsoft/playwright-mcp.git
cd playwright-mcp

# Build the image
docker build -t mcr.microsoft.com/playwright/mcp .
```

### Dockerfile Overview

The Dockerfile uses a multi-stage build:

```dockerfile theme={null}
ARG PLAYWRIGHT_BROWSERS_PATH=/ms-playwright

# Base stage: minimal runtime dependencies
FROM node:22-bookworm-slim AS base
ARG PLAYWRIGHT_BROWSERS_PATH
ENV PLAYWRIGHT_BROWSERS_PATH=${PLAYWRIGHT_BROWSERS_PATH}
WORKDIR /app

# Install dependencies and Playwright system deps
RUN npm ci --omit=dev && \
    npx -y playwright-core install-deps chromium

# Browser stage: download Chromium
FROM base AS browser
RUN npx -y playwright-core install --no-shell chromium

# Runtime stage: final image
FROM base
ENV NODE_ENV=production
ENV PLAYWRIGHT_MCP_OUTPUT_DIR=/tmp/playwright-output

USER node
COPY --from=browser --chown=node:node ${PLAYWRIGHT_BROWSERS_PATH} ${PLAYWRIGHT_BROWSERS_PATH}
COPY --chown=node:node packages/playwright-mcp/cli.js packages/playwright-mcp/package.json ./

ENTRYPOINT ["node", "cli.js", "--headless", "--browser", "chromium", "--no-sandbox"]
```

## Docker Compose

For more complex deployments, use Docker Compose:

```yaml docker-compose.yml theme={null}
version: '3.8'

services:
  playwright-mcp:
    image: mcr.microsoft.com/playwright/mcp
    container_name: playwright-mcp
    ports:
      - "8931:8931"
    environment:
      - NODE_ENV=production
      - PLAYWRIGHT_MCP_OUTPUT_DIR=/tmp/playwright-output
    command: [
      "node",
      "cli.js",
      "--headless",
      "--browser", "chromium",
      "--no-sandbox",
      "--port", "8931",
      "--host", "0.0.0.0"
    ]
    volumes:
      - playwright-output:/tmp/playwright-output
    restart: unless-stopped

volumes:
  playwright-output:
```

### Start with Docker Compose

```bash theme={null}
docker-compose up -d
```

## Environment Variables

Pass environment variables to configure the server:

```bash theme={null}
docker run -d -i --rm --init \
  --name playwright \
  -p 8931:8931 \
  -e PLAYWRIGHT_MCP_HEADLESS=true \
  -e PLAYWRIGHT_MCP_BROWSER=chromium \
  -e PLAYWRIGHT_MCP_ISOLATED=true \
  mcr.microsoft.com/playwright/mcp
```

## Volume Mounts

### Output Directory

Mount a volume to persist output files:

```bash theme={null}
docker run -d -i --rm --init \
  --name playwright \
  -p 8931:8931 \
  -v $(pwd)/output:/tmp/playwright-output \
  mcr.microsoft.com/playwright/mcp
```

### Configuration File

Mount a configuration file:

```bash theme={null}
docker run -d -i --rm --init \
  --name playwright \
  -p 8931:8931 \
  -v $(pwd)/config.json:/app/config.json \
  mcr.microsoft.com/playwright/mcp \
  node cli.js --config /app/config.json --port 8931 --host 0.0.0.0
```

## Security Considerations

<Warning>
  Always use `--no-sandbox` when running in Docker due to kernel restrictions. The container itself provides isolation.
</Warning>

### Best Practices

<CardGroup cols={2}>
  <Card title="Run as non-root" icon="user-shield">
    The official image runs as the `node` user for security.
  </Card>

  <Card title="Use isolated mode" icon="lock">
    Enable `--isolated` to prevent persistent state between sessions.
  </Card>

  <Card title="Restrict network access" icon="network-wired">
    Use Docker networks and firewalls to limit container connectivity.
  </Card>

  <Card title="Limit resources" icon="gauge-high">
    Use Docker resource constraints (`--memory`, `--cpus`) to prevent resource exhaustion.
  </Card>
</CardGroup>

## Troubleshooting

### Container exits immediately

Ensure you're using `-i` (interactive) flag for STDIO mode or properly configuring HTTP mode with `--port` and `--host 0.0.0.0`.

### Connection refused

Verify that:

* The container is running: `docker ps`
* Port mapping is correct: `-p 8931:8931`
* Server is bound to `0.0.0.0` not `localhost`
* Firewall allows the connection

### Browser crashes

Add `--no-sandbox` flag (required in most Docker environments) and ensure sufficient memory is available.
