From fd3bcdd41816802f78395bf1919aee31efc1f200 Mon Sep 17 00:00:00 2001 From: vitya Date: Wed, 26 Aug 2026 09:39:27 +0300 Subject: [PATCH] =?UTF-8?q?runbook:=20pilorama98.ru=20(pilonuxt)=20VDS=20d?= =?UTF-8?q?eploy=20=E2=80=94=20=D1=80=D0=B5=D1=81=D1=82=D0=B0=D1=80=D1=82?= =?UTF-8?q?=20vs=20=D0=BF=D0=B5=D1=80=D0=B5=D1=81=D0=B1=D0=BE=D1=80=D0=BA?= =?UTF-8?q?=D0=B0,=20=D1=81=D1=82=D0=B5=D0=BA=2016?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../concepts/pilorama98-vds-deploy-runbook.md | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 .wiki/concepts/pilorama98-vds-deploy-runbook.md diff --git a/.wiki/concepts/pilorama98-vds-deploy-runbook.md b/.wiki/concepts/pilorama98-vds-deploy-runbook.md new file mode 100644 index 0000000..9b9dc32 --- /dev/null +++ b/.wiki/concepts/pilorama98-vds-deploy-runbook.md @@ -0,0 +1,160 @@ +--- +title: "pilorama98.ru (pilonuxt) — VDS deploy runbook (стек 16, рестарт/пересборка)" +type: concept +tags: [pilorama98, pilonuxt, vds, deploy, docker, portainer, nuxt, runbook, cache] +related: [concepts/portainer-stack-management-vds.md, concepts/pilonuxt-restart-vs-redeploy-2026-08-16.md, concepts/admin-api-embed-pilonuxt.md] +sources: [] +updated: 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:` — тег = короткий 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; builder + `yarn 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) + +```python +# Portainer docker-proxy (Python, urllib; либо .tmp/restart-stack16.ps1) +POST https://portainer.vds.kzntsv.site/api/auth {"username":"vitya","password":""} +POST https://portainer.vds.kzntsv.site/api/endpoints/1/docker/containers/pilonuxt/restart # body пустой, 204 +``` + +Verify: `GET .../containers/pilonuxt/json` → `State.StartedAt` обновился, образ тот же. + +## Пересборка + деплой (новый код) + +```bash +# 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: . + +# 3. Push +echo '' | docker login registry.kzntsv.site -u vitya --password-stdin +docker push registry.kzntsv.site/pilonuxt: + +# 4. Portainer PUT стека 16 (замена тега, env preserve, pullImage) +# GET /api/stacks/16/file → regexp замена pilonuxt: → pilonuxt: +# PUT /api/stacks/16?endpointId=1 {stackFileContent, env: , 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 + +```bash +# контейнер на новом образе, Up +GET https://portainer.vds.kzntsv.site/api/endpoints/1/docker/containers/pilonuxt/json +# → Config.Image == registry.kzntsv.site/pilonuxt:, 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= +# → volume_price (каноническое поле). ⚠️ voulme_price — legacy-опечатка, НЕ использовать (фикс 38c26c7 + 8943333). +# консоль контейнера: docker logs pilonuxt — без краш-лупа +``` + +**БД напрямую** (если надо сверить запечённое): docker exec mssql через Portainer +(`/containers/mssql/exec`, sqlcmd `-U snolla -P `), +`SELECT ... FROM Products WHERE Slug IN (...)`, Content — JSON-массив `[{name,value}]` +(array-canon 0.11.0). + +## Rollback + +Тот же PUT стека 16 с прежним тегом (`` → ``), `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 404 +- `340c0e7` — выпил «Строительство каркасных домов» +- `8b7e8c4` — SMTP-фикс (noreply@snolla.com) + +## Gotchas + +1. **Рестарт ≠ деплой.** Письма прогера «подтяни цены» = рестарт (кэш), письма + «задеплой коммит X» = пересборка. Не путать (см. инцидент 2026-08-16 и 2026-08-26). +2. **`voulme_price` — legacy-опечатка** (в БД застыла на старых значениях). Канон — + `volume_price` (loader пишет сюда с фикса 38c26c7). Категории рендерят `volume_price` + с фикса 8943333 (2026-08-26). Если где-то снова всплывёт voulme_price — это баг кода. +3. **PUT стека сбрасывает env** — всегда передавать `env` в payload (у 16 — `[]`). +4. **src/generated/ обязателен в build-контексте** — иначе билд лезет в mssql + (ensure-schema), а в чистом git clone COPY упадёт. +5. **VERDACCIO_TOKEN — build-secret, не ARG** (слой-чистота). Токен — живой JWT, + протухает — при 401 на verdaccio перевыпустить (books-ci, см. verdaccio-token-lifecycle). +6. **Kэш viewModel в памяти контейнера** — рестарт сбрасывает, пересборка не нужна + при смене данных. Проверено 2026-08-16 («цена за м³ подтянулась») и 2026-08-26 + (категории voulme_price — это был баг кода, не кэш). +7. **Конфиг запечён в образ** — правки `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]] — похожий канал (другой хост/стек)