Образ собран под linux/amd64 и выложен как notbigghost/kbc2d — теги 1.0.0,
latest и 8d17bc8 указывают на один digest sha256:932d881d. В Dockerfile
добавлены метки OCI: версия, хеш коммита и ссылка на репозиторий, чтобы
образ на сервере однозначно сопоставлялся с состоянием исходников.
docker-compose.server.yml самодостаточен: тянет готовый образ из реестра,
исходников не требует, на сервер переносится одним файлом. Кампания —
единственный сервис, поднимающийся по up -d; проверки (vulkaninfo,
preflight, calibrate, dry-run) вынесены в профиль check и сами не
стартуют. Порядок проверок задан документацией: карта, сценарии,
калибровка, смета — и только потом счёт.
Политика перезапуска on-failure, а не unless-stopped: кампания завершается
штатно с кодом 0, и «перезапускать всегда» крутило бы контейнер вхолостую
по кругу, тогда как падение и перезагрузку хоста on-failure подхватывает,
а --resume продолжает с места. Журнал ограничен по размеру: девяносто
часов вывода иначе съедят диск, полные логи каждого прогона всё равно
лежат в out/<id>/log.txt.
Проверено локально из каталога без исходников: образ тянется из реестра,
смоук проходит, результаты ложатся на хост. Часть с картой проверяема
только на сервере — здесь запрос устройства ожидаемо отвергается
«no adapters were found», что само по себе подтверждает, что резервация
GPU в compose действует.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
98 lines
5.6 KiB
YAML
98 lines
5.6 KiB
YAML
# Развёртывание кампании на сервере с NVIDIA. Этот файл САМОДОСТАТОЧЕН: он тянет готовый образ
|
||
# из реестра и исходников репозитория не требует. Скопировать на сервер достаточно его одного.
|
||
#
|
||
# mkdir -p ~/kbc2d && cd ~/kbc2d
|
||
# curl -O <ссылка на этот файл> # либо просто перенести файл руками
|
||
#
|
||
# docker compose -f docker-compose.server.yml --profile check run --rm vulkan
|
||
# docker compose -f docker-compose.server.yml --profile check run --rm preflight
|
||
# docker compose -f docker-compose.server.yml --profile check run --rm calibrate
|
||
# docker compose -f docker-compose.server.yml --profile check run --rm plan
|
||
# docker compose -f docker-compose.server.yml up -d
|
||
# docker compose -f docker-compose.server.yml logs -f
|
||
#
|
||
# Порядок именно такой. Сначала vulkan: если карта не видна, кампания молча уйдёт считать
|
||
# ничего — точнее, откажется стартовать на первом же прогоне, но узнать об этом через час
|
||
# обиднее, чем через минуту. Потом preflight (каждый сценарий стартует на два шага), потом
|
||
# calibrate (замер MLUPS этой машины), и только потом сама кампания.
|
||
#
|
||
# Результаты складываются в ./out на хосте — около 4.4 ГБ гифок и рядов за полный проход.
|
||
|
||
name: kbc2d
|
||
|
||
# ── общая часть всех сервисов ────────────────────────────────────────────────
|
||
x-kbc2d: &kbc2d
|
||
image: notbigghost/kbc2d:1.0.0
|
||
pull_policy: missing
|
||
volumes:
|
||
- ./out:/work/bench/out
|
||
environment:
|
||
# ГЛАВНОЕ МЕСТО ВСЕГО ФАЙЛА. NVIDIA Container Toolkit подкладывает внутрь Vulkan-ICD
|
||
# (nvidia_icd.json) только если в этом списке есть `graphics`. С одним `compute` wgpu не
|
||
# увидит НИ ОДНОГО адаптера, и решатель откажется стартовать с --backend gpu. В образе
|
||
# значение уже прописано, здесь оно продублировано явно — чтобы его было видно тому, кто
|
||
# читает compose, а не Dockerfile.
|
||
NVIDIA_DRIVER_CAPABILITIES: compute,utility,graphics
|
||
NVIDIA_VISIBLE_DEVICES: all
|
||
# Оценки в часах драйвер считает из этих чисел. Умолчания взяты с другой машины —
|
||
# подставьте сюда то, что напечатает профиль calibrate.
|
||
KBC2D_GPU_MLUPS: ${KBC2D_GPU_MLUPS:-1200}
|
||
KBC2D_CPU_MLUPS: ${KBC2D_CPU_MLUPS:-22}
|
||
deploy:
|
||
resources:
|
||
reservations:
|
||
devices:
|
||
- driver: nvidia
|
||
count: all
|
||
capabilities: [gpu]
|
||
|
||
services:
|
||
# ── сама кампания: единственный сервис, который поднимается по `up -d` ──────
|
||
campaign:
|
||
<<: *kbc2d
|
||
container_name: kbc2d-campaign
|
||
# --resume пропускает всё, у чего уже есть summary.json: перезапуск продолжает с места,
|
||
# а не начинает заново. Именно поэтому перезапуск здесь безопасен и дёшев.
|
||
command: ["--resume"]
|
||
# on-failure, а НЕ unless-stopped: кампания завершается штатно с кодом 0, и политика
|
||
# «перезапускать всегда» после её окончания крутила бы контейнер вхолостую по кругу.
|
||
# Падение (OOM, перезагрузка хоста) даёт ненулевой код и будет подхвачено.
|
||
restart: on-failure:5
|
||
stop_grace_period: 30s
|
||
# Девяносто часов вывода — это сотни мегабайт журнала; без ограничения он съест диск.
|
||
# Полные логи каждого прогона всё равно лежат в out/<id>/log.txt.
|
||
logging:
|
||
driver: json-file
|
||
options:
|
||
max-size: "50m"
|
||
max-file: "5"
|
||
|
||
# ── проверки перед запуском (профиль check, сами не поднимаются) ────────────
|
||
vulkan:
|
||
<<: *kbc2d
|
||
profiles: ["check"]
|
||
entrypoint: ["vulkaninfo"]
|
||
command: ["--summary"]
|
||
|
||
preflight:
|
||
<<: *kbc2d
|
||
profiles: ["check"]
|
||
entrypoint: ["python3"]
|
||
command: ["preflight.py"]
|
||
|
||
calibrate:
|
||
<<: *kbc2d
|
||
profiles: ["check"]
|
||
command: ["--calibrate"]
|
||
|
||
plan:
|
||
<<: *kbc2d
|
||
profiles: ["check"]
|
||
command: ["--dry-run"]
|
||
# ── если результаты нужны не под root ────────────────────────────────────────
|
||
# Контейнер работает от root, поэтому файлы в ./out окажутся root:root. Чтобы они
|
||
# принадлежали вам, добавьте в x-kbc2d строку
|
||
# user: "${UID}:${GID}"
|
||
# и запускайте как UID=$(id -u) GID=$(id -g) docker compose -f … up -d
|
||
# (каталог ./out при этом должен быть создан заранее и принадлежать вам).
|