Files
admin/.wiki/concepts/pilorama98-vds-deploy-runbook.md

161 lines
11 KiB
Markdown
Raw 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.
---
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:<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; 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":"<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` обновился, образ тот же.
## Пересборка + деплой (новый код)
```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:<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
```bash
# контейнер на новом образе, 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 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]] — похожий канал (другой хост/стек)