# Web API Server # Multi-stage build for smaller final image FROM python:3.11.12-slim AS builder # Install uv COPY --from=ghcr.io/astral-sh/uv:0.10 /uv /usr/local/bin/uv WORKDIR /app # Layer 1: Install dependencies only (cached unless pyproject.toml changes) COPY pyproject.toml README.md ./ RUN uv sync --no-dev --all-extras --no-install-project # Layer 2: Install Playwright browsers (cached with dependencies) RUN uv run playwright install chromium --with-deps # Layer 3: Copy source and install project (fast — deps already cached) COPY src/ ./src/ RUN uv sync --no-dev --all-extras # Production image FROM python:3.11.12-slim WORKDIR /app # Install Playwright dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ libnss3 libnspr4 libdbus-1-3 libatk1.0-0 libatk-bridge2.0-0 \ libcups2 libdrm2 libxkbcommon0 libatspi2.0-0 libxcomposite1 \ libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2 \ libcairo2 libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf-2.0-0 \ libgtk-3-0 libx11-6 libx11-xcb1 libxcb1 libxext6 libxrender1 \ fonts-liberation fonts-noto-color-emoji libopus0 libharfbuzz0b \ libglib2.0-0 libxshmfence1 \ && rm -rf /var/lib/apt/lists/* # Create non-root user RUN groupadd -r webuser && useradd -r -g webuser -d /home/webuser -m webuser # Copy virtual environment from builder COPY --from=builder /app/.venv /app/.venv # Copy Playwright browsers to non-root user's home COPY --from=builder /root/.cache/ms-playwright /home/webuser/.cache/ms-playwright # Copy source code COPY src/ ./src/ # Set ownership RUN chown -R webuser:webuser /app /home/webuser # Set environment variables ENV PATH="/app/.venv/bin:$PATH" ENV PYTHONUNBUFFERED=1 ENV WEB_HOST=0.0.0.0 ENV WEB_PORT=51100 ENV PLAYWRIGHT_BROWSERS_PATH=/home/webuser/.cache/ms-playwright # Switch to non-root user USER webuser # Health check HEALTHCHECK --interval=30s --timeout=10s --retries=3 \ CMD python -c "import urllib.request; import os; urllib.request.urlopen(f'http://localhost:{os.environ.get(\"WEB_PORT\", 51100)}/health')" || exit 1 # Expose port EXPOSE 51100 # Run the server CMD ["python", "-m", "web.cli"]