11 KiB
title, type, tags, related, sources, updated
| title | type | tags | related | sources | updated | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| pilorama98.ru (pilonuxt) — VDS deploy runbook (стек 16, рестарт/пересборка) | concept |
|
|
2026-08-26 |
pilorama98.ru (pilonuxt) — деплой на прод
⚙️ СЛУЖЕБНЫЙ РАНБУК — только для администратора проекта
.admin. Применять/выполнять шаги может только.admin(оператор проекта admin). Другим проектам/агентам — читать по запросу, не выполнять. Из проекта не выносить: не копировать в другие вики, не пересказывать, не публиковать. Нужен деплой или прод-операция по этому ранбуку — поставить задачу админу (.admin) и написать письмо. Админ выполняет, остальные верифицируют.
Прод https://pilorama98.ru / www.pilorama98.ru = Nuxt-фронт из монорепы
victor/pilorama98.ru (apps/web, Nuxt 4 / Nitro node-server preset). Хостится
контейнером на VDS kzntsv, управляется Portainer-стеком. Легаси IIS (RUVDS) —
rollback-путь, не используется.
Параметры
| Что | Значение |
|---|---|
| Хост | VDS kzntsv 89.253.255.94 |
| Стек Portainer | Id 16, name pilonuxt, endpointId 1 |
| Образ | registry.kzntsv.site/pilonuxt:<git-sha7> — тег = короткий sha монорепы |
| Compose source-of-truth | admin/host-stacks/vds-kzntsv/pilonuxt.compose.yml (в репо .admin) |
| Репо/код | victor/pilorama98.ru @ master; apps/web/Dockerfile |
| БД | mssql.kzntsv.site:1433 MoreThenCms (конфиг запечён в образ, см. ниже) |
| Версии на проде | см. инвентарь ниже (текущий 2026-08-26: 8943333) |
Артефакты
- Образ: двухстадийный
apps/web/Dockerfile(node:22-bookworm-slim; builderyarn workspace nuxt-app build→.output; runner копирует@imgнативы sharp). Сборка — workspace-сборка из КОРНЯ монорепы:-f apps/web/Dockerfile .(lockfile/.yarnrc.yml в корне). Тег = короткий git-sha коммита. - VERDACCIO_TOKEN — build-secret (
--secret id=verdaccio_token,env=VERDACCIO_TOKEN), живой JWT, не ARG/ENV (не оседает в слоях). Источник:pass vds-kzntsv/full-env→VERDACCIO_CI_TOKEN(books-ci, len ~312, 2 точки). - Registry auth:
docker login registry.kzntsv.site -u vitya(парольREGISTRY_PASSизpass vds-kzntsv/full-env). - Portainer auth: JWT
POST /api/auth—vitya/PORTAINER_ADMIN_PASSизpass vds-kzntsv/full-env. - Конфиг запечён в
apps/web/config/внутри образа (MSSQL/SMTP/imgproxy ключи, siteId) — runtime env-override не настроен (решение 2026-06-14).
Две разные операции (не путать!)
| Операция | Когда нужна | Как делается | Что сбрасывает |
|---|---|---|---|
| Рестарт контейнера | Контент/цены в БД изменились, код тот же | Portainer POST /api/endpoints/1/docker/containers/pilonuxt/restart |
In-memory viewModel кэш content-api — свежие данные из MoreThenCms подтягиваются без пересборки |
| Пересборка (деploy) | Изменился код (новый git-sha в монорепе) | build → push → Portainer PUT стек 16 | Код + всё вышеперечисленное |
Симптом «данные в БД есть, на фронте нет» (цены/контент устарели) → рестарт, не деплой. Симптом «500 на странице со стеком @snolla/core / lodash _.find» → код/данные, не кэш — рестарт не лечит, нужна пересборка (см. concepts/pilonuxt-restart-vs-redeploy-2026-08-16.md).
Рестарт контейнера (кэш viewModel)
# Portainer docker-proxy (Python, urllib; либо .tmp/restart-stack16.ps1)
POST https://portainer.vds.kzntsv.site/api/auth {"username":"vitya","password":"<PORTAINER_ADMIN_PASS из pass vds-kzntsv/full-env>"}
POST https://portainer.vds.kzntsv.site/api/endpoints/1/docker/containers/pilonuxt/restart # body пустой, 204
Verify: GET .../containers/pilonuxt/json → State.StartedAt обновился, образ тот же.
Пересборка + деплой (новый код)
# 1. Проверить коммит: локально master == origin/master, коммит — потомок
cd ~/projects/pilorama98.ru
git fetch origin master && git log --oneline -1 master
# 2. Build (из корня монорепы, build-secret). Предусловия:
# - apps/web/src/generated/ populated (после yarn install) — иначе ensure-schema лезет в mssql
# - .yarnrc.yml c npmAlwaysAuth: true (канон в репо)
VERDACCIO_TOKEN=$(pass show vds-kzntsv/full-env | grep '^VERDACCIO_CI_TOKEN=' | cut -d= -f2-)
docker build -f apps/web/Dockerfile --secret id=verdaccio_token,env=VERDACCIO_TOKEN \
-t registry.kzntsv.site/pilonuxt:<sha7> .
# 3. Push
echo '<REGISTRY_PASS из pass vds-kzntsv/full-env>' | docker login registry.kzntsv.site -u vitya --password-stdin
docker push registry.kzntsv.site/pilonuxt:<sha7>
# 4. Portainer PUT стека 16 (замена тега, env preserve, pullImage)
# GET /api/stacks/16/file → regexp замена pilonuxt:<old7> → pilonuxt:<new7>
# PUT /api/stacks/16?endpointId=1 {stackFileContent, env: <preserve>, prune:false, pullImage:true}
⚠️ PUT сбрасывает env-массив, если не передать env в payload — у стека 16 env пуст
(Env: []), передавать literal [] (плейсхолдер-трюк при PS: -replace '"__ENV__"','[]').
⚠️ Кодировка: тело PUT слать UTF-8-байтами (PowerShell 5.1 коррапит кириллицу, gotcha 9
concepts/portainer-stack-management-vds.md).
⚠️ Синхронизировать source-of-truth host-stacks/vds-kzntsv/pilonuxt.compose.yml (тег) после PUT.
Verify
# контейнер на новом образе, Up
GET https://portainer.vds.kzntsv.site/api/endpoints/1/docker/containers/pilonuxt/json
# → Config.Image == registry.kzntsv.site/pilonuxt:<sha7>, State.running
# страницы (SSR, live): категория бруска + карточки товаров
curl -ksS https://pilorama98.ru/catalog/brus-estestvennoj-vlazhnosti | grep -c '19 500'
curl -ksS https://pilorama98.ru/shop/products/brusok-estestvennoj-vlazhnosti-40-50-6000 | grep -c '19 500'
# viewModel API (content-api, свежие данные из БД):
# GET https://pilorama98.ru/snolla/stores/F42F4113-EC3E-4644-8D0E-70D3F430219D/products/viewModel?slug=<slug>
# → volume_price (каноническое поле). ⚠️ voulme_price — legacy-опечатка, НЕ использовать (фикс 38c26c7 + 8943333).
# консоль контейнера: docker logs pilonuxt — без краш-лупа
БД напрямую (если надо сверить запечённое): docker exec mssql через Portainer
(/containers/mssql/exec, sqlcmd -U snolla -P <pass из pass mssql-vds/...>),
SELECT ... FROM Products WHERE Slug IN (...), Content — JSON-массив [{name,value}]
(array-canon 0.11.0).
Rollback
Тот же PUT стека 16 с прежним тегом (<new7> → <old7>), pullImage:true.
Старые теги висят в registry (инвентарь ниже). RTO ~30-60с (пересоздание контейнера).
Инвентарь образов (откат-цепочка)
8943333— текущий (2026-08-26: fix catalog voulme_price→volume_price)64c2539— предыдущий (admin-api 0.11.0 array-canon)1128ddc— core 0.26.7 (фикс 500_.find)f876e70— заглушки каталога → фото (3 шт.)24a13da— «Брус антисептированный» фото40806b1— services-[slug] настоящий SSR 404340c0e7— выпил «Строительство каркасных домов»8b7e8c4— SMTP-фикс (noreply@snolla.com)
Gotchas
- Рестарт ≠ деплой. Письма прогера «подтяни цены» = рестарт (кэш), письма «задеплой коммит X» = пересборка. Не путать (см. инцидент 2026-08-16 и 2026-08-26).
voulme_price— legacy-опечатка (в БД застыла на старых значениях). Канон —volume_price(loader пишет сюда с фикса 38c26c7). Категории рендерятvolume_priceс фикса 8943333 (2026-08-26). Если где-то снова всплывёт voulme_price — это баг кода.- PUT стека сбрасывает env — всегда передавать
envв payload (у 16 —[]). - src/generated/ обязателен в build-контексте — иначе билд лезет в mssql (ensure-schema), а в чистом git clone COPY упадёт.
- VERDACCIO_TOKEN — build-secret, не ARG (слой-чистота). Токен — живой JWT, протухает — при 401 на verdaccio перевыпустить (books-ci, см. verdaccio-token-lifecycle).
- Kэш viewModel в памяти контейнера — рестарт сбрасывает, пересборка не нужна при смене данных. Проверено 2026-08-16 («цена за м³ подтянулась») и 2026-08-26 (категории voulme_price — это был баг кода, не кэш).
- Конфиг запечён в образ — правки
config/требуют пересборки; runtime env-override не настроен (решение 2026-06-14).
Связи
- concepts/pilonuxt-restart-vs-redeploy-2026-08-16.md — рестарт vs пересборка, инцидент 2026-08-16
- concepts/portainer-stack-management-vds.md — общий Portainer-канон (JWT, gotchas 9/10)
- concepts/admin-api-embed-pilonuxt.md — admin-api embed, array-canon
- Репо-вики:
apps/web/.wiki/concepts/docker-deploy.md(сборка образа, деплой) - Ранбук stostayer: concepts/stostayer-web-deploy-runbook.md — похожий канал (другой хост/стек)