# Образ решателя и валидационной кампании.
#
# Поддерживает два способа добраться до видеокарты, и выбирать между ними не нужно —
# доступным окажется ровно один:
#
#  1. НАСТОЯЩИЙ LINUX-СЕРВЕР с драйвером NVIDIA. Vulkan-ICD подкладывает внутрь
#     NVIDIA Container Toolkit, и только если в NVIDIA_DRIVER_CAPABILITIES есть
#     `graphics` — с одним `compute` wgpu не увидит ни одного адаптера. Запуск через
#     docker-compose.server.yml.
#
#  2. WSL2. Драйвер NVIDIA для Linux там отсутствует как класс: карта отдаётся через
#     /dev/dxg по протоколу WDDM, а нативный libGLX_nvidia про него не знает и
#     enumerate возвращает ноль устройств. Зато с /dev/dxg умеет говорить dzn (Dozen) —
#     драйвер Mesa, транслирующий Vulkan в D3D12. Он в образе и лежит. NVIDIA Container
#     Toolkit при этом НЕ НУЖЕН: нужен проброс устройства и монтирование /usr/lib/wsl,
#     где Microsoft держит libd3d12.so. Запуск через docker-compose.wsl.yml.
#
# Сборка и быстрая проверка:
#   docker build -t kbc2d docs/theory/2d_solver
#   docker compose -f docker-compose.wsl.yml --profile check run --rm vulkan

# ── сборка ───────────────────────────────────────────────────────────────────
# Версия тулчейна закреплена: та же, на которой решатель собирался и проверялся.
FROM rust:1.97-bookworm AS build
WORKDIR /src

# Сначала только манифесты — тогда слой с зависимостями переиспользуется, пока они не менялись.
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo 'fn main() {}' > src/main.rs  && cargo build --release --locked 2>/dev/null || true  && rm -rf src

COPY src ./src
# touch нужен, чтобы cargo не спутал новые исходники с заглушкой из слоя выше
RUN touch src/main.rs && cargo build --release --locked

# ── исполнение ───────────────────────────────────────────────────────────────
# База Arch, а не debian-slim, по одной причине: dzn собирают не все дистрибутивы.
# В mesa-vulkan-drivers Debian и Ubuntu его нет (проверено по списку файлов пакета),
# в Arch он лежит отдельным пакетом vulkan-dzn той же версии Mesa, что и на хосте WSL.
FROM archlinux:base

ARG VERSION=dev
ARG REVISION=unknown
LABEL org.opencontainers.image.title="kbc2d"
LABEL org.opencontainers.image.description="Двумерный решатель LBM D2Q9 с энтропийным столкновением KBC"
LABEL org.opencontainers.image.version="${VERSION}"
LABEL org.opencontainers.image.revision="${REVISION}"
LABEL org.opencontainers.image.source="https://gitea.arseniev.info/NotBigGhost/TurbulenceCAD"

# Справка, руководства и переводы занимают в базе Arch заметно больше, чем сам
# драйвер, а в контейнере не нужны никому. NoExtract прописывается ДО установки.
RUN { echo 'NoExtract = usr/share/man/*'; \
      echo 'NoExtract = usr/share/doc/*'; \
      echo 'NoExtract = usr/share/info/*'; \
      echo 'NoExtract = usr/share/locale/*'; \
      echo 'NoExtract = usr/share/i18n/*'; } >> /etc/pacman.conf \
 && pacman -Syu --noconfirm --needed \
        vulkan-icd-loader vulkan-dzn vulkan-tools python \
 && pacman -Scc --noconfirm \
 && rm -rf /var/cache/pacman/pkg/* /var/lib/pacman/sync/* \
           /usr/share/man /usr/share/doc /usr/share/info /usr/share/locale

# Проверка на этапе сборки: без dzn образ бесполезен для WSL, и узнать об этом надо
# здесь, а не через час после старта кампании.
RUN ls /usr/share/vulkan/icd.d/ && ls /usr/share/vulkan/icd.d/dzn_icd*.json > /dev/null

# Для пути 1 (настоящий сервер). На WSL эти переменные ни на что не влияют.
ENV NVIDIA_VISIBLE_DEVICES=all
ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility,graphics

WORKDIR /work
COPY --from=build /src/target/release/kbc2d /work/target/release/kbc2d
COPY bench /work/bench
RUN chmod +x /work/bench/run_campaign.sh

# Кампания идёт десятки часов, поэтому по умолчанию образ НЕ запускает её: случайный
# `docker run` покажет смету и выйдет.
WORKDIR /work/bench
ENTRYPOINT ["./run_campaign.sh"]
CMD ["--dry-run"]
