All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Successful in 1m9s
CI / openapi-codegen-check (pull_request) Successful in 2m23s
CI / backend-tests (pull_request) Successful in 18m6s
Ничего не апгрейдит. Убирает три способа собрать образ не тем, что в репозитории. 1. tradein-mvp/backend/uv.lock — удалён (файл был untracked, в .gitignore с рождения). Мера — uv-workspace, сборка берёт КОРНЕВОЙ tradein-mvp/uv.lock (`context: ./tradein-mvp`, `COPY pyproject.toml uv.lock ./` + `uv sync --frozen`). Лок, созданный `uv lock` из backend/, не читает никто, и он тихо разошёлся с рабочим: на 2026-08-29 в нём pillow 12.2.0, starlette 1.0.1, python-multipart 0.0.29, pydantic-settings 2.14.1, weasyprint 68.1 — пять пакетов с открытыми advisory, которых в реальной сборке Меры нет вообще. Именно он подмешал пять фантомных строк в OSV-скан этой серии. Строка .gitignore остаётся (второй лок не нужен), но теперь с объяснением почему — иначе следующий читатель снимет ignore и закоммитит призрак. 2. backend/Dockerfile — `COPY pyproject.toml uv.lock* ./` + `if [ -f uv.lock ]; then uv sync --frozen ...; else uv sync ...; fi` → без глоба и без фолбэка. Глоб + фолбэк означали: пропал лок — сборка не падает, а молча переключается на резолв «свежайшее из диапазонов pyproject». Образ собрался бы с версиями, которых никто не видел ни в одном PR. Теперь пропажа лока роняет COPY. 3. tradein-mvp/browser/Dockerfile — `pip install "camoufox[geoip]" aiohttp` без единого пина. У сайдкара нет лока вообще, так что любая пересборка (в том числе на несвязанном коммите) тянула свежайший camoufox, а с ним другой playwright — под который НЕ написан sed-патч coreBundle.js в том же файле. Запинено по факту прод-контейнера tradein-browser: camoufox 0.5.5, playwright 1.60.0, aiohttp 3.14.3. playwright явно, хотя и транзитивный (camoufox 0.5.5 → playwright<1.61): патч завязан на конкретную сборку драйвера. Там же переписан комментарий «Апгрейд playwright невозможен — camoufox 0.4.11 pinned»: неверны обе половины. camoufox не был запинен ни на что, а 0.4.11 в проде не стоит с неизвестно каких пор — контейнер сейчас несёт 0.5.5 и playwright 1.60.0. Версии сняты с живого прод-контейнера, наличие на PyPI проверено.
116 lines
3.9 KiB
Docker
116 lines
3.9 KiB
Docker
# syntax=docker/dockerfile:1.7
|
||
#
|
||
# Multi-target build:
|
||
# target=runner — lean image для backend (uvicorn) и beat. ~1.4 ГБ.
|
||
# target=runner-with-chromium — image для worker (Playwright fetch). ~1.6 ГБ.
|
||
#
|
||
# Local: docker compose сам выбирает target по сервису (см. docker-compose.yml).
|
||
# Prod: CI пушит 2 GHCR-образа: gendesign-backend (lean) и gendesign-worker (chromium).
|
||
|
||
# ---- builder ----
|
||
FROM python:3.12-slim AS builder
|
||
|
||
ENV PYTHONUNBUFFERED=1 \
|
||
PYTHONDONTWRITEBYTECODE=1 \
|
||
UV_COMPILE_BYTECODE=1 \
|
||
UV_LINK_MODE=copy
|
||
|
||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||
apt-get update && apt-get install -y --no-install-recommends \
|
||
build-essential \
|
||
libpq-dev \
|
||
libgdal-dev \
|
||
libproj-dev \
|
||
libgeos-dev
|
||
|
||
RUN pip install --no-cache-dir uv
|
||
|
||
WORKDIR /app
|
||
|
||
# Без глоба и без фолбэка: uv.lock ОБЯЗАТЕЛЕН. `uv.lock*` + `if [ -f uv.lock ]`
|
||
# означали, что пропавший лок не ломает сборку, а тихо переключает её на резолв
|
||
# «свежайшее из диапазонов pyproject» — образ собирался бы с версиями, которых
|
||
# никто не видел ни в одном PR, и воспроизвести прод-сборку было бы нечем.
|
||
# Теперь пропажа лока = падение COPY, то есть красный билд вместо незаметной
|
||
# подмены зависимостей.
|
||
COPY pyproject.toml uv.lock ./
|
||
# uv-кеш переживает между билдами: при неизменном lock'е sync ~5 сек вместо 1-2 мин.
|
||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||
uv sync --frozen --no-dev
|
||
|
||
COPY app ./app
|
||
COPY alembic.ini ./
|
||
COPY alembic ./alembic
|
||
|
||
|
||
# ---- runner (lean — без Chromium) ----
|
||
FROM python:3.12-slim AS runner
|
||
|
||
ENV PYTHONUNBUFFERED=1 \
|
||
PYTHONDONTWRITEBYTECODE=1 \
|
||
PATH="/app/.venv/bin:$PATH"
|
||
|
||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||
apt-get update && apt-get install -y --no-install-recommends \
|
||
libpq5 \
|
||
libgdal36 \
|
||
libproj25 \
|
||
libgeos-c1t64 \
|
||
libcairo2 \
|
||
libpango-1.0-0 \
|
||
libpangoft2-1.0-0 \
|
||
fonts-dejavu-core \
|
||
curl \
|
||
tesseract-ocr \
|
||
tesseract-ocr-rus \
|
||
&& useradd --create-home --uid 1000 app
|
||
|
||
WORKDIR /app
|
||
|
||
COPY --from=builder --chown=app:app /app/.venv /app/.venv
|
||
COPY --from=builder --chown=app:app /app/app /app/app
|
||
COPY --from=builder --chown=app:app /app/alembic.ini /app/alembic.ini
|
||
COPY --from=builder --chown=app:app /app/alembic /app/alembic
|
||
|
||
USER app
|
||
|
||
EXPOSE 8000
|
||
|
||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||
|
||
|
||
# ---- runner-with-chromium (для worker) ----
|
||
# Наследуется от lean runner, добавляет Chromium-libs + Playwright-binary (~200 MB).
|
||
FROM runner AS runner-with-chromium
|
||
|
||
USER root
|
||
|
||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||
apt-get update && apt-get install -y --no-install-recommends \
|
||
# Chromium runtime libs (раньше заходили через `playwright install --with-deps`)
|
||
libnss3 \
|
||
libnspr4 \
|
||
libdbus-1-3 \
|
||
libatk1.0-0 \
|
||
libatk-bridge2.0-0 \
|
||
libcups2 \
|
||
libdrm2 \
|
||
libxkbcommon0 \
|
||
libxcomposite1 \
|
||
libxdamage1 \
|
||
libxfixes3 \
|
||
libxrandr2 \
|
||
libgbm1 \
|
||
libasound2t64 \
|
||
libatspi2.0-0
|
||
|
||
# Playwright Chromium binary под root → shared dir, чтобы и app-user мог использовать.
|
||
ENV PLAYWRIGHT_BROWSERS_PATH=/opt/playwright
|
||
RUN mkdir -p $PLAYWRIGHT_BROWSERS_PATH \
|
||
&& /app/.venv/bin/playwright install chromium \
|
||
&& chmod -R a+rX $PLAYWRIGHT_BROWSERS_PATH
|
||
|
||
USER app
|