55 lines
2.2 KiB
Docker
55 lines
2.2 KiB
Docker
# ── Stage 1: dependency resolver ─────────────────────────────────────────────
|
|
FROM python:3.11-slim AS builder
|
|
|
|
# Install uv
|
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
|
|
|
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 2: runtime ──────────────────────────────────────────────────────────
|
|
FROM python:3.11-slim AS runtime
|
|
|
|
# ── Chromium + matching system ChromeDriver ───────────────────────────────────
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
ca-certificates curl chromium chromium-driver \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# ── uv + venv from builder ────────────────────────────────────────────────────
|
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
|
|
|
WORKDIR /app
|
|
|
|
# Make the venv's binaries the default Python
|
|
ENV PATH="/app/.venv/bin:$PATH" \
|
|
PYTHONUNBUFFERED=1 \
|
|
PYTHONDONTWRITEBYTECODE=1 \
|
|
# Tell undetected-chromedriver where Chrome lives
|
|
CHROME_BINARY=/usr/bin/chromium \
|
|
CHROMEDRIVER_PATH=/usr/bin/chromedriver \
|
|
# Always run headless inside Docker
|
|
HEADLESS=true
|
|
|
|
# ── Application code ──────────────────────────────────────────────────────────
|
|
COPY . .
|
|
|
|
# Copy this after the application so a host venv can never replace it.
|
|
COPY --from=builder /app/.venv /app/.venv
|
|
|
|
# Patch Debian's version-matched driver at build time. Runtime jobs require no
|
|
# ChromeDriver network download.
|
|
RUN PYTHONPATH=. python scripts/patch_driver.py && mkdir -p data logs
|
|
|
|
# Non-root user for safety
|
|
RUN useradd -m -u 1001 seed && chown -R seed:seed /app
|
|
USER seed
|
|
|
|
EXPOSE 8000
|
|
|
|
CMD ["python", "main.py", "admin"]
|