bone_2026/Dockerfile_cuda

107 lines
6.2 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DXA Quality Assessment — контейнер для инференса (GPU / CUDA)
#
# Сборка: docker build -f Dockerfile_cuda.txt -t dxa-quality:cuda .
# Запуск: docker run --gpus all -p 8000:8000 dxa-quality:cuda
# или: docker compose --profile cuda up -d dxa-cuda
#
# База — тот же python:3.11-slim, что и у CPU-варианта, а CUDA и cuDNN приходят
# внутри колёс torch с индексом cu126. Отдельный nvidia/cuda-образ не нужен:
# контейнеру достаточно драйвера хоста, который подставляет
# nvidia-container-toolkit по флагу --gpus all (или секции deploy в compose).
# Требуется драйвер NVIDIA >= 525; для H200 (sm_90) в кластере он заведомо новее.
#
# Индекс cu118 в прежней версии файла не работал: torch 2.8.0 под CUDA 11.8 не
# публикуется (последняя версия там — 2.7.1), поэтому сборка падала на pip.
# Для 2.8.0 доступны только cu126 и cu128; выбран cu126 как наиболее
# распространённый. Под H200 нужен torch>=2.5, sm_90 поддерживается.
#
# Чекпоинт лежит ВНУТРИ образа (см. Dockerfile): монтировать пути не нужно.
FROM python:3.11-slim
# libgl1/libglib2.0-0 нужны opencv (импортируется через зависимости проекта),
# libgomp1 — для параллельных циклов torch. Список совпадает с CPU-образом.
RUN apt-get update && apt-get install -y --no-install-recommends \
libgl1 \
libglib2.0-0 \
libgomp1 \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# --- PyTorch под CUDA 12.6 ---
# CUDA-колёса ставим первыми и с явным индексом: иначе pip взял бы с PyPI сборку
# под CUDA 12.6/12.8 произвольной ревизии. torchvision 0.23.0 — парная к torch
# 2.8.0 версия (другие комбинации несовместимы).
RUN pip install --no-cache-dir --upgrade pip \
&& pip install --no-cache-dir \
--index-url https://download.pytorch.org/whl/cu126 \
torch==2.8.0 torchvision==0.23.0
# --- Остальные зависимости ---
# Отдельным слоем и после torch: список версий один на оба образа
# (requirements.txt), а уже установленный torch==2.8.0+cu126 pip повторно не
# поставит — требование torch==2.8.0 считается выполненным, потому что локальная
# метка сборки при сравнении версий не учитывается.
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
# --- Код ---
COPY src ./src
# Скрипт пакетной обработки (оценка берёт его из корня образа).
COPY run.sh ./run.sh
RUN chmod +x ./run.sh
# Smoke-проверка импорта: падает на сборке, если расходятся зависимости или
# модуль не найден, вместо тихой 500-й на каждом запросе в рантайме.
RUN python -c "import src.main; print('app import ok')"
# --- Проверка статики для офлайн-работы ---
# Веб-интерфейс не должен зависеть от CDN: Tailwind и FontAwesome лежат в
# src/api/static/vendor и src/api/static/webfonts (см. index.html).
RUN python -c "import os; \
files=['src/api/static/vendor/tailwind.js','src/api/static/vendor/fontawesome.css', \
'src/api/static/webfonts/fa-solid-900.woff2']; \
missing=[f for f in files if not os.path.exists(f)]; \
assert not missing, f'missing frontend assets: {missing}'; \
print('frontend assets ok')"
# --- Чекпоинт внутри образа ---
# Условие приёмки: модель уже в образе, чтобы проверяющему не приходилось
# указывать путь к каталогу с весами. models/dxa_model.pth отслеживается git,
# поэтому копирование работает и в CI.
COPY models/dxa_model.pth /app/models/dxa_model.pth
# Проверка, что чекпоинт читается и содержит всё нужное для инференса, а также
# что сборка torch видит CUDA: без этого проблемы всплыли бы только в рантайме.
RUN python -c "import torch; \
ckpt=torch.load('/app/models/dxa_model.pth', map_location='cpu', weights_only=False); \
missing=[k for k in ('model_state_dict','backbone','head','threshold') if k not in ckpt]; \
assert not missing, f'checkpoint missing keys: {missing}'; \
print('checkpoint ok:', ckpt['backbone'], ckpt['head'], 'threshold', ckpt['threshold']); \
print('torch', torch.__version__, 'cuda built:', torch.version.cuda)"
# --- Переменные окружения ---
# Читается кодом только DXA_MODEL_PATH (src/main.py). MODEL_PATH, DATA_PATH,
# ANNOTATION_DIR swarm передаёт по инерции от прежней версии — код их не
# использует, и они ни на что не влияют.
ENV PYTHONUNBUFFERED=1 \
PYTHONPATH=/app \
DXA_MODEL_PATH=/app/models/dxa_model.pth \
MODEL_PATH=/app/models \
DATA_PATH=/app/data \
ANNOTATION_DIR=/app/data/annotations
RUN mkdir -p /app/data /app/logs
EXPOSE 8000
# HEALTHCHECK опирается на /api/v1/health, который отдаёт model_loaded.
# На GPU-устройстве старт дольше: даём запас по start-period.
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --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"]