diff --git a/Dockerfile b/Dockerfile index 0cc21c3..b003ac9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,10 +2,9 @@ # make build # Build all Docker images (admin + worker) # docker compose up -d # Start all services # -# 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 +# - admin stage: python:3.11-slim (FastAPI only, no Chrome) +# - worker stage: Playwright Noble with Python + Chromium pre-installed +# from your local registry mirror. # ── Build args ───────────────────────────────────────────────────────────────── ARG BASE_IMAGE=python:3.11-slim @@ -13,18 +12,15 @@ ARG BASE_IMAGE=python:3.11-slim # ── Stage 1: dependency resolver ───────────────────────────────────────────── FROM python:3.11-slim AS builder -# Keep the build independent of GHCR; dependencies already use official PyPI. RUN pip install --no-cache-dir uv==0.11.31 WORKDIR /app -# Copy only dependency manifests first (cache layer) COPY pyproject.toml uv.lock* ./ -# Install deps into an isolated prefix so we can copy them cleanly RUN uv sync --frozen --no-dev --no-install-project -# ── Stage 2a: admin runtime (python:3.11-slim, no Chrome) ──────────────────── +# ── Stage 2a: admin runtime (python:3.11-slim, no Chrome needed) ────────────── FROM ${BASE_IMAGE} AS admin WORKDIR /app @@ -46,49 +42,50 @@ EXPOSE 8000 CMD ["python", "main.py", "admin"] -# ── 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 +# ── Stage 2b: worker runtime (Playwright Noble + Python) ────────────────────── +# Base image: oci.reg.darano.ir//mcr.microsoft.com/playwright:v1.62.0-noble +# This image already ships: +# - Ubuntu 24.04 LTS (Noble Numbat) +# - Chromium + matching ChromeDriver +# - Python 3.12 +# - ffmpeg, xvfb, and other browser utilities +# We only need to install our Python project dependencies. + +FROM oci.reg.darano.ir//mcr.microsoft.com/playwright:v1.62.0-noble AS worker + +# The Playwright image ships Python via /usr/bin/python3 but pip is not in PATH. +# Install uv to manage our project dependencies. +# The Playwright Noble image includes a minimal uv shim at /usr/local/bin/uv — +# if it's not present, bootstrap it via curl. +RUN which uv >/dev/null 2>&1 || \ + (curl -LsSf https://astral.sh/uv/install.sh | \ + UV_INSTALL_DIR=/usr/local sh 2>&1 >/dev/null) ENV PATH="/app/.venv/bin:$PATH" \ PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ - # Chromium binary (installed below) + # Chromium is pre-installed at /usr/bin/chromium CHROME_BINARY=/usr/bin/chromium \ - CHROMEDRIVER_PATH=/app/drivers/chromedriver \ - # Always run headless inside Docker + CHROMEDRIVER_PATH=/usr/bin/chromedriver \ 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 manifests first (stable cache layer) COPY pyproject.toml uv.lock* ./ -# Install deps into a venv -RUN pip install --no-cache-dir uv==0.11.31 \ - && uv sync --frozen --no-dev --no-install-project +# Install project deps into a venv targeting this image's Python 3.12 +RUN uv sync --frozen --no-dev --no-install-project -# Copy app code (busts cache on code changes, not deps) +# Copy app code COPY . . -# 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 \ +# mkdir for volumes, user for security +RUN mkdir -p data logs recordings \ + && useradd -m -u 1001 seed 2>/dev/null || true \ && chown -R seed:seed /app 2>/dev/null || true USER seed -# CMD is overridden in docker-compose.yml to use RQ worker +# CMD overridden in docker-compose.yml to use RQ worker CMD ["rq", "worker", "--url", "redis://redis:6379/0", "batch"]