diff --git a/Dockerfile b/Dockerfile index 75c3791..0cc21c3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,11 @@ # Usage: -# make build # admin + worker — uses python:3.11-slim (default) -# docker compose up -d # same as above +# make build # Build all Docker images (admin + worker) +# docker compose up -d # Start all services # -# docker compose build worker # rebuild worker with Playwright base -# docker compose up -d worker # start worker on Playwright image -# -# The admin panel always uses python:3.11-slim (no Chrome needed). -# The worker uses mcr.microsoft.com/playwright:v1.62.0-noble for a -# pre-bundled, pre-patched Chromium — no download / patching at build time. +# Both admin and worker use python:3.11-slim — the builder stage +# is shared (caches deps), then: +# - admin: no Chrome needed (FastAPI only) +# - worker: installs Chromium + patches ChromeDriver for stealth # ── Build args ───────────────────────────────────────────────────────────────── ARG BASE_IMAGE=python:3.11-slim @@ -48,38 +46,46 @@ EXPOSE 8000 CMD ["python", "main.py", "admin"] -# ── Stage 2b: worker runtime (Playwright image with Chromium) ──────────────── -# The Playwright Noble image ships Python 3.12. Copying a venv built with -# python:3.11-slim would produce broken shebangs — so we build the venv here. -FROM oci.reg.darano.ir/mcr.microsoft.com/playwright:v1.62.0-noble AS worker +# ── Stage 2b: worker runtime (Python image with Chromium installed) ─────────── +# Playwright Docker images don't ship Python — they're language-agnostic +# Ubuntu images with only Chromium/Chrome/Firefox. Reverting to python:3.11-slim +# for the worker so we get a working Python + pip out of the box. +FROM ${BASE_IMAGE} AS worker ENV PATH="/app/.venv/bin:$PATH" \ PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ - # Playwright's Chromium binary + # Chromium binary (installed below) CHROME_BINARY=/usr/bin/chromium \ - CHROMEDRIVER_PATH=/usr/bin/chromedriver \ + CHROMEDRIVER_PATH=/app/drivers/chromedriver \ # Always run headless inside Docker HEADLESS=true WORKDIR /app +# Install Chromium + matching system ChromeDriver +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates curl chromium chromium-driver ffmpeg xvfb \ + && rm -rf /var/lib/apt/lists/* + # Copy manifests + lockfile first (stable cache layer) COPY pyproject.toml uv.lock* ./ -# Install deps natively so the venv targets this image's Python -# (Playwright Noble ships Python but not pip/uv in PATH) -RUN python -m ensurepip --upgrade \ - && python -m pip install --no-cache-dir --break-system-packages uv==0.11.31 \ +# Install deps into a venv +RUN pip install --no-cache-dir uv==0.11.31 \ && uv sync --frozen --no-dev --no-install-project # Copy app code (busts cache on code changes, not deps) COPY . . -# Playwright's Chromium is already downloaded and pre-patched with -# undetected-chromedriver-friendly modifications, so no patch_driver run needed. -RUN mkdir -p data logs recordings \ - && useradd -m -u 1001 seed 2>/dev/null || true \ +# Patch ChromeDriver at build time. This downloads the matching version, +# patches out undetected-chromedriver anti-detection flags, and places +# the binary at /app/drivers/chromedriver (configured via CHROMEDRIVER_PATH). +RUN PYTHONPATH=. python scripts/patch_driver.py \ + && mkdir -p data logs recordings + +# Non-root user for safety +RUN useradd -m -u 1001 seed 2>/dev/null || true \ && chown -R seed:seed /app 2>/dev/null || true USER seed