AURORA-1677: Dockerfile fix

This commit is contained in:
tsygankoviva 2026-10-26 18:57:11 +03:00
parent da2b9a1611
commit 77a2fb216b
4 changed files with 23 additions and 9 deletions

View File

@ -1,5 +1,6 @@
# syntax=docker/dockerfile:1
# Образ scan-gateway для dev и `make check-full`. Контекст сборки — корень репозитория.
# Библиотека передаётся контекстом statements (make docker-build, STATEMENTS_DIR).
# Платформенные пакеты raisa_* (Nexus) в образ не ставятся — та же логика, что в `make venv`.
FROM python:3.11-slim
@ -9,15 +10,11 @@ ENV PYTHONUNBUFFERED=1 \
WORKDIR /app/api
COPY api/requirements.txt ./requirements.txt
RUN grep -Ev '^(raisa_|pylib_ai)' requirements.txt > /tmp/req.txt \
&& pip install --no-cache-dir -r /tmp/req.txt \
RUN --mount=type=bind,from=statements,target=/tmp/statements,rw \
grep -v '^raisa_' requirements.txt > /tmp/req.txt \
&& pip install --no-cache-dir -r /tmp/req.txt /tmp/statements \
&& rm /tmp/req.txt
# Локальная библиотека передаётся дополнительным контекстом (make docker-build).
COPY --from=statements /setup.py /setup.cfg /pyproject.toml /MANIFEST.in /VERSION /requirements.txt /README.md /tmp/statements/
COPY --from=statements /arm_statements /tmp/statements/arm_statements
RUN pip install --no-cache-dir /tmp/statements && rm -rf /tmp/statements
COPY api/ ./
EXPOSE 8000

View File

@ -7,6 +7,7 @@ COMPOSE_FILE ?= ../docs/dev/docker-compose.yml
COMPOSE_PROJECT ?= arm-ka
IMAGE ?= scan-gateway:dev
STATEMENTS_DIR ?= ../pylib_ai_arm_statements
STATEMENTS_TAG ?= v0.1.1
.PHONY: help venv install lint test test-integration check docker-build check-full up emulator golden-update
@ -51,7 +52,12 @@ check: lint test
# Образ собирается без Nexus (raisa_* в образ не ставятся, см. Dockerfile). Тесты в образе не запускаются:
# tests/ в нём есть, но api/.env.test исключён через .dockerignore, поэтому pytest внутри контейнера не пройдёт.
docker-build:
docker build --build-context statements="$(STATEMENTS_DIR)" -t $(IMAGE) .
@release=$$(git -C "$(STATEMENTS_DIR)" rev-parse --verify "refs/tags/$(STATEMENTS_TAG)^{commit}") || \
{ echo "Ошибка: в библиотеке отсутствует тег $(STATEMENTS_TAG); выполните git fetch --tags в $(STATEMENTS_DIR)" >&2; exit 1; }; \
head=$$(git -C "$(STATEMENTS_DIR)" rev-parse HEAD) || exit 1; \
[ "$$head" = "$$release" ] || \
{ echo "Ошибка: HEAD библиотеки не совпадает с $(STATEMENTS_TAG)" >&2; exit 1; }
docker build --build-context "statements=$(STATEMENTS_DIR)" -t $(IMAGE) .
# Полная проверка перед PR. Шаги вызываются последовательно через $(MAKE), а не как пререквизиты:
# так порядок check -> test-integration -> docker-build и остановка на первой ошибке гарантированы и при make -j.

View File

@ -423,3 +423,14 @@ make golden-update # пересобрать эталоны нормализ
- Реальные фикстуры: `aep_3.json` (баланс и ОФР), `aep_6.json` — успешные ответы, `aep_3_ofr.json`, `aep_5.json`,
`aep_8_form4.json` — ответы-ошибки (`INVALID_DOCUMENT`; `data_ocr` — объект с пустыми полями и `table_structure: []`).
- Контейнера `scan-emulator` в compose пока нет.
Сборка Docker использует BuildKit-контекст `statements` из `STATEMENTS_DIR`
(по умолчанию `../pylib_ai_arm_statements`). Другой путь:
`make docker-build STATEMENTS_DIR=/путь/к/библиотеке`. Библиотека устанавливается
из исходников вместе с requirements; её версия должна соответствовать закреплённой
в requirements. Остальные зависимости загружаются из пакетного индекса.
Перед локальной сборкой `make docker-build` проверяет совпадение HEAD библиотеки
с тегом `STATEMENTS_TAG` (по умолчанию `v0.1.1`). Получить тег:
`git -C ../pylib_ai_arm_statements fetch origin --tags`.
Незакоммиченные изменения разрешены и попадают в сборку из `STATEMENTS_DIR`.

View File

@ -17,7 +17,7 @@
1. **Установка локального пакета через uv.** `STATEMENTS_DIR` задаёт источник. `make venv` фильтрует `^(raisa_|pylib_ai)` при установке requirements и затем ставит пакет из пути; `make install` создаёт окружение при необходимости и выполняет переустановку через `--reinstall-package`. Так изменения исходников попадают в окружение после явной команды. Editable-установка не выбрана, чтобы поведение совпадало с установкой пакета в образ; копирование и публикация в PyPI исключены выбранным способом поставки.
2. **Версия зависимости и версия результата.** `requirements.txt` фиксирует ожидаемую `0.1.1`, runtime использует `statements_version()`. Тест приложения сравнивает версию с метаданными установленного дистрибутива вместо чтения удалённого пути. Отсутствие версии остаётся ошибкой старта, текст предлагает `make install`. Структура контракта не меняется. Фильтрация requirements означает, что версия локального источника отдельно сверяется при приёмке: сама запись `==0.1.1` не ограничивает установку из пути.
3. **Разделение проверок библиотеки и сервиса.** Удаляются копия, её `testpaths`, аргумент mypy и `statements-check` из `check-full`. Ruff считает `arm_statements` сторонним импортом. Для пакета без `py.typed` mypy получает адресный `follow_untyped_imports = true`, чтобы использовать существующие аннотации вместо общего подавления ошибок. Проверки адаптера, результата и golden остаются в шлюзе; тесты самой библиотеки принадлежат библиотеке.
4. **Docker build context `statements`.** Make передаёт путь через `--build-context`; Dockerfile фильтрует зависимости и копирует только исходники пакета и необходимые файлы сборки, устанавливает пакет, затем удаляет временный источник. Исходники не монтируются при запуске. Расширение основного контекста до всего workspace не выбрано: оно привязывает сборку к структуре соседних проектов.
4. **Docker build context `statements`.** Make передаёт путь через `--build-context`; Dockerfile исключает raisa_* из requirements, временно монтирует контекст через RUN --mount и устанавливает библиотеку вместе с requirements одним вызовом pip с проверкой закреплённой версии. Исходники не монтируются при запуске. Расширение основного контекста до всего workspace не выбрано: оно привязывает сборку к структуре соседних проектов.
5. **Документация и общие контракты.** README, CLAUDE и сообщения шлюза описывают библиотеку. Основные спеки обновятся при отдельном sync/archive, исторические change'и сохраняются. Общие JSON Schema остаются побайтовой копией источника; историческое описание коммита копии внутри схемы требует отдельного согласованного изменения в docs, если будет обновляться.
## Risks / Trade-offs