runbook: pilorama98.ru (pilonuxt) VDS deploy — рестарт vs пересборка, стек 16
This commit is contained in:
160
.wiki/concepts/pilorama98-vds-deploy-runbook.md
Normal file
160
.wiki/concepts/pilorama98-vds-deploy-runbook.md
Normal file
@@ -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:<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]] — похожий канал (другой хост/стек)
|
||||||
Reference in New Issue
Block a user