# Playwright Proxy MCP Server Dockerfile
# Multi-stage build with manual file filtering for production
# Build arguments with defaults
ARG PYTHON_VERSION=3.12
# Stage 1: Copy all source files (no .dockerignore filtering)
FROM python:${PYTHON_VERSION}-slim AS source
WORKDIR /source
COPY . .
# Stage 2: Filter files for production (remove dev-only files)
FROM python:${PYTHON_VERSION}-slim AS filtered-source
WORKDIR /filtered
# Copy from source and manually filter out development files
COPY --from=source /source /filtered
# Remove development-only files and directories
RUN rm -rf \
# Git
.git \
.gitignore \
# Python artifacts
__pycache__ \
*.py[cod] \
*.egg-info \
.eggs \
dist \
build \
*.egg \
# Virtual environments
.venv \
venv \
# Testing
.pytest_cache \
.coverage \
htmlcov \
tests \
# IDEs
.idea \
.vscode \
# Documentation (keep README.md)
docs \
CLAUDE.md \
# Environment files
.env \
.env.local \
.env.*.local \
# Docker files
Dockerfile* \
docker-compose*.yml \
.docker \
dockerignore.reference \
# Dev container
.devcontainer \
# Claude
.claude \
# Logs
*.log \
logs \
# Temporary files
tmp \
temp \
*.tmp \
*.bak
# Stage 3: Base production image
FROM python:${PYTHON_VERSION}-slim AS base
# Install system dependencies including build tools for Python packages with C extensions
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
curl \
ca-certificates \
# For mcp-mapped-resource-lib MIME detection
libmagic1 \
# For Node.js (playwright-mcp)
gnupg \
# Build tools for Python packages with C extensions (e.g., ruamel-yaml-clibz)
gcc \
g++ \
make \
python3-dev \
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# Install uv package manager
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
# Set working directory
WORKDIR /workspace
# Copy filtered production files
COPY --from=filtered-source /filtered /workspace
# Install aria-snapshot-parser from local directory first
# This must be installed before the main project since the main project depends on it
RUN if [ -d "/workspace/src/aria_snapshot_parser" ]; then \
cd /workspace/src/aria_snapshot_parser && uv pip install --system .; \
fi
# Install production dependencies and the package itself into system Python
RUN uv sync --frozen --no-dev 2>/dev/null || uv sync --no-dev && \
uv pip install --system -e .
# Remove build tools to reduce image size (keep runtime libraries)
RUN apt-get purge -y --auto-remove \
gcc \
g++ \
make \
python3-dev \
&& rm -rf /var/lib/apt/lists/*
# Pre-install @playwright/mcp and its Playwright browsers
# This ensures browser versions match the @playwright/mcp requirements
# We must run 'npx playwright install' from within the @playwright/mcp package
# to ensure the correct playwright version installs its matching browsers
RUN npm install -g @playwright/mcp@latest && \
cd /usr/lib/node_modules/@playwright/mcp && \
npx playwright install chromium --with-deps && \
npx playwright install chrome --with-deps
# Create directories for blob storage and playwright output
RUN mkdir -p /mnt/blob-storage /workspace/playwright-output
# Stage 4: Production stage
FROM base AS production
ENV PYTHONUNBUFFERED=1
# Mount points for persistence
VOLUME ["/mnt/blob-storage", "/workspace/playwright-output"]
CMD ["playwright-proxy-mcp"]
# Stage 5: Development stage with all files and additional tools
FROM python:${PYTHON_VERSION}-slim AS development
# Install system dependencies including Java for PMD, wget for downloading tools, and Go for mcptools
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
curl \
wget \
unzip \
ca-certificates \
sudo \
gnupg \
lsb-release \
default-jre \
golang-go \
&& rm -rf /var/lib/apt/lists/*
# Install Docker CLI for Docker-outside-of-Docker (DooD) support
RUN install -m 0755 -d /etc/apt/keyrings && \
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc && \
chmod a+r /etc/apt/keyrings/docker.asc && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null && \
apt-get update && \
apt-get install -y docker-ce-cli docker-compose-plugin && \
rm -rf /var/lib/apt/lists/*
# Create vscode user with sudo privileges
ARG CREATE_VSCODE_USER=true
RUN if [ "$CREATE_VSCODE_USER" = "true" ]; then \
groupadd --gid 1000 vscode && \
useradd --uid 1000 --gid 1000 -m -s /bin/bash vscode && \
echo "vscode ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/vscode && \
chmod 0440 /etc/sudoers.d/vscode && \
groupadd docker || true && \
usermod -aG docker vscode; \
fi
# Set working directory
WORKDIR /workspace
# Install Node.js for Claude Code CLI
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# Install Claude Code CLI globally
RUN npm install -g @anthropic-ai/claude-code
# Install PMD for code duplication detection
ARG PMD_VERSION=7.10.0
RUN wget -q "https://github.com/pmd/pmd/releases/download/pmd_releases%2F${PMD_VERSION}/pmd-dist-${PMD_VERSION}-bin.zip" -O /tmp/pmd.zip && \
unzip -q /tmp/pmd.zip -d /opt && \
mv /opt/pmd-bin-${PMD_VERSION} /opt/pmd && \
ln -s /opt/pmd/bin/pmd /usr/local/bin/pmd && \
rm /tmp/pmd.zip
# Install mcptools for MCP server testing
RUN go install github.com/f/mcptools/cmd/mcptools@latest && \
ln -s /root/go/bin/mcptools /usr/local/bin/mcptools
# Install uv package manager for root
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
# Install uv for vscode user if created
RUN if [ "$CREATE_VSCODE_USER" = "true" ]; then \
su - vscode -c "curl -LsSf https://astral.sh/uv/install.sh | sh"; \
fi
# Copy ALL files from source (including tests, CLAUDE.md, etc.)
COPY --from=source /source /workspace
# Install system dependencies for Playwright and libmagic
RUN apt-get update && apt-get install -y --no-install-recommends \
libmagic1 \
&& rm -rf /var/lib/apt/lists/*
# Pre-install @playwright/mcp and its Playwright browsers
# This ensures browser versions match the @playwright/mcp requirements
# We must run 'npx playwright install' from within the @playwright/mcp package
# to ensure the correct playwright version installs its matching browsers
RUN npm install -g @playwright/mcp@latest && \
cd /usr/lib/node_modules/@playwright/mcp && \
npx playwright install chromium --with-deps && \
npx playwright install chrome --with-deps
# Create directories for blob storage and playwright output
RUN mkdir -p /mnt/blob-storage /workspace/playwright-output
# Set ownership of workspace to vscode user
RUN chown -R vscode:vscode /workspace
# Install Playwright browsers for vscode user as well
# This is needed because the devcontainer runs as vscode user, not root
RUN su - vscode -c "cd /usr/lib/node_modules/@playwright/mcp && npx playwright install chromium --with-deps && npx playwright install chrome --with-deps"
# Don't run uv sync here - let postCreateCommand handle it as vscode user
# This avoids permission issues with the .venv directory
ENV PYTHONUNBUFFERED=1
CMD ["/usr/bin/sleep", "infinity"]