# DXA Quality Assessment — контейнер для инференса (CPU) # # Сборка: docker build -t dxa-quality . # Запуск: docker run -v /path/to/data:/data -p 8000:8000 dxa-quality # # Требования методики: зависимости с зафиксированными версиями и запуск # локально без обращения к внешним сервисам. Inference не использует # предобученные веса из интернета — они уже внутри чекпоинта, поэтому # при запуске сеть не нужна. FROM python:3.11-slim # libgl1/libglib2.0-0 нужны opencv (импортируется через зависимости проекта), # libgomp1 — для параллельных циклов torch. RUN apt-get update && apt-get install -y --no-install-recommends \ libgl1 \ libglib2.0-0 \ libgomp1 \ && rm -rf /var/lib/apt/lists/* WORKDIR /app # --- Слой зависимостей: отдельно от кода, чтобы кэшировался --- # Все версии зафиксированы, torch ставится с CPU-индексом: образ для инференса # не требует GPU, а версия из PyPI на Linux подтянула бы CUDA-колёса. COPY requirements.txt ./ RUN pip install --no-cache-dir --upgrade pip \ && pip install --no-cache-dir \ --extra-index-url https://download.pytorch.org/whl/cpu \ -r requirements.txt # --- Код --- COPY src ./src COPY models ./models # Скрипт пакетной обработки (оценка берёт его из корня образа). COPY run.sh ./run.sh RUN chmod +x ./run.sh # smoke-проверка: чекпоинт должен читаться. Падает на сборке, если модели нет, # вместо тихого 500 на каждом запросе в рантайме. RUN python -c "import os, torch; p='models/dxa_model.pth'; \ assert os.path.exists(p), f'missing checkpoint {p}'; \ ck=torch.load(p, map_location='cpu', weights_only=False); \ assert 'model_state_dict' in ck, 'checkpoint has no model_state_dict'; \ print('checkpoint ok:', ck.get('backbone'), ck.get('head'))" ENV PYTHONUNBUFFERED=1 \ PYTHONPATH=/app \ DXA_MODEL_PATH=/app/models/dxa_model.pth EXPOSE 8000 # HEALTHCHECK опирается на /api/v1/health, который отдаёт model_loaded. HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ CMD python -c "import urllib.request,sys; \ r=urllib.request.urlopen('http://127.0.0.1:8000/api/v1/health', timeout=5); \ sys.exit(0 if r.status==200 else 1)" CMD ["python", "-m", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]