Docker provides an isolated environment for running Playwright MCP, which is recommended for production deployments and security-sensitive scenarios.
The Docker implementation currently only supports headless Chromium.
Spawned Container Mode
In this mode, the MCP client spawns a new Docker container for each session.
{
"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
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:
{
"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
# 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:
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:
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
Environment Variables
Pass environment variables to configure the server:
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:
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:
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
Always use --no-sandbox when running in Docker due to kernel restrictions. The container itself provides isolation.
Best Practices
Run as non-root
The official image runs as the node user for security.
Use isolated mode
Enable --isolated to prevent persistent state between sessions.
Restrict network access
Use Docker networks and firewalls to limit container connectivity.
Limit resources
Use Docker resource constraints (--memory, --cpus) to prevent resource exhaustion.
Troubleshooting
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.