From 9a92ff0b87d993e171dce721c1f032b6683618b9 Mon Sep 17 00:00:00 2001 From: vitya Date: Sun, 5 Jul 2026 14:32:55 +0300 Subject: [PATCH] =?UTF-8?q?chore(vds):=20mem=5Flimit=20512m=20=D0=B2=D1=81?= =?UTF-8?q?=D0=B5=D0=BC=D1=83=20=D1=82=D0=B8=D1=80=D0=B0=D0=B6=D1=83=20sno?= =?UTF-8?q?lla=20(5=20=D1=81=D1=82=D0=B5=D0=BA=D0=BE=D0=B2=20live=20+=20co?= =?UTF-8?q?mpose-=D0=BA=D0=BE=D0=BF=D0=B8=D0=B8=20+=20=D0=B2=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8-=D0=BA=D0=BE=D0=BD=D0=B2=D0=B5=D0=BD=D1=86=D0=B8=D1=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Тираж snolla (labtools.ru/17, emspb/18, labtools.pro/19, tandemmebel/20, kupimknigi/21) шёл без mem_limit → cgroup-cap = вся память хоста (12.9 GiB), одна течь могла съесть весь бокс. Выставил 512m (baseline ~100-200M, 2.5-5x запас) на всех 5 живых стеках через env-preserving Portainer PUT + синхронизировал source-of-truth compose. Все healthy, limit=536870912 подтверждён, labtools.pro 200. Конвенция «app-стек обязан нести mem_limit» закреплена в portainer-stack-management-vds § Convention + step 6 snolla-bump-рецепта. Co-Authored-By: Claude Opus 4.8 (1M context) --- .wiki/concepts/portainer-stack-management-vds.md | 16 ++++++++++++++++ .../snolla-live-prod-inplace-image-bump.md | 2 ++ host-stacks/vds-kzntsv/emspb.compose.yml | 1 + host-stacks/vds-kzntsv/kupimknigi.compose.yml | 1 + host-stacks/vds-kzntsv/labtools-pro.compose.yml | 1 + host-stacks/vds-kzntsv/labtools.compose.yml | 1 + host-stacks/vds-kzntsv/tandemmebel.compose.yml | 1 + 7 files changed, 23 insertions(+) diff --git a/.wiki/concepts/portainer-stack-management-vds.md b/.wiki/concepts/portainer-stack-management-vds.md index 9f47f62..3d98919 100644 --- a/.wiki/concepts/portainer-stack-management-vds.md +++ b/.wiki/concepts/portainer-stack-management-vds.md @@ -68,6 +68,22 @@ curl -ksS -X POST "$PORTAINER_URL/api/stacks/create/standalone/string?endpointId -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" --data "$PAYLOAD" ``` +## Convention: `mem_limit` на app-стеках (обязательно) + +**Каждый app/site-стек несёт `mem_limit`.** Без него cgroup-`limit` = вся память хоста (12.9 GiB) → +одна течь в контейнере может съесть весь бокс, а не упереться в свой потолок. С `restart: unless-stopped` +упор в лимит = OOM-kill контейнера + авто-подъём (изоляция вместо каскада на всю машину). + +- **standalone-стек (не swarm) → ключ `mem_limit`**, НЕ `deploy.resources.limits.memory` (тот игнорится вне swarm). +- Значение = ~2.5–5× наблюдаемого пика. snolla-сайты (Node SSR, baseline ~100–200 MB) → **`512m`**. + Прочерк-пример: owncloud oCIS → `1g`. +- Ставить в момент создания/правки стека — не откладывать. Проверка постфактум: `ops.docker.stats ` + поле `limit` == заданному (512m = 536870912), не 13890813952. +- **Синхронизировать обе копии**: боевой стек в Portainer (PUT) И source-of-truth compose в + `admin/host-stacks/vds-kzntsv/.compose.yml`. Иначе следующий redeploy из гита откатит лимит. + +Применено 2026-07-05 ко всему тиражу snolla (labtools.ru/17, emspb/18, labtools.pro/19, tandemmebel/20, kupimknigi/21) → все `512m`. + ## Gotchas 1. **`env_file: .env` ломает Portainer string-mode** — Portainer не материализует `.env` файл в `/data/compose//`. Compose pull fails: `env file /data/compose//.env not found`. Fix: `sed '/^\s*env_file:/d'` + передавать env через API `env` array. diff --git a/.wiki/concepts/snolla-live-prod-inplace-image-bump.md b/.wiki/concepts/snolla-live-prod-inplace-image-bump.md index 00920c9..7535254 100644 --- a/.wiki/concepts/snolla-live-prod-inplace-image-bump.md +++ b/.wiki/concepts/snolla-live-prod-inplace-image-bump.md @@ -80,6 +80,8 @@ META=/tmp/st.json node put-stack.js .compose.yml`) — обновить тег + коммент rollback. +**Проверить `mem_limit`** на стеке (обязателен для всех app-стеков — см. [[portainer-stack-management-vds]] § Convention). +snolla → `512m`; если стек его ещё не несёт (старые до 2026-07-05) — добавить в этот же PUT и в compose-копию. Борд-таска 🟢, отчёт прогу (Notify=сам сайт, минуя workshop), rollback-тег остаётся в registry. ## put-stack.js (env-preserving Portainer stack PUT) diff --git a/host-stacks/vds-kzntsv/emspb.compose.yml b/host-stacks/vds-kzntsv/emspb.compose.yml index cafd57b..1926f7e 100644 --- a/host-stacks/vds-kzntsv/emspb.compose.yml +++ b/host-stacks/vds-kzntsv/emspb.compose.yml @@ -27,6 +27,7 @@ services: container_name: emspb image: registry.kzntsv.site/emspb:95a5c42 # git-sha victor/emspb.ru master (snolla 0.42.1, bump 2026-07-05; prev b6e361a=0.28.4=rollback) restart: unless-stopped + mem_limit: 512m # guardrail от runaway: snolla baseline ~100-200M; OOM в контейнере → restart:unless-stopped поднимет. standalone-compose → mem_limit (НЕ deploy.resources — то swarm-only). environment: NODE_ENV: production TZ: Europe/Moscow diff --git a/host-stacks/vds-kzntsv/kupimknigi.compose.yml b/host-stacks/vds-kzntsv/kupimknigi.compose.yml index c927fa7..53475ff 100644 --- a/host-stacks/vds-kzntsv/kupimknigi.compose.yml +++ b/host-stacks/vds-kzntsv/kupimknigi.compose.yml @@ -30,6 +30,7 @@ services: container_name: kupimknigi image: registry.kzntsv.site/kupimknigi:9608ff6 # git-sha victor/kupimknigi.spb.ru (snolla 0.42.0 / core 0.24.0 / data 0.14.1) restart: unless-stopped + mem_limit: 512m # guardrail от runaway: snolla baseline ~100-200M; OOM в контейнере → restart:unless-stopped поднимет. standalone-compose → mem_limit (НЕ deploy.resources — то swarm-only). environment: NODE_ENV: production TZ: Europe/Moscow diff --git a/host-stacks/vds-kzntsv/labtools-pro.compose.yml b/host-stacks/vds-kzntsv/labtools-pro.compose.yml index 7894fdc..b5eec6b 100644 --- a/host-stacks/vds-kzntsv/labtools-pro.compose.yml +++ b/host-stacks/vds-kzntsv/labtools-pro.compose.yml @@ -29,6 +29,7 @@ services: container_name: labtools-pro image: registry.kzntsv.site/labtools-pro:0610432 # git-sha victor/labtools.pro master (snolla 0.42.1, bump 2026-07-05; prev 7bd9fae=0.28.7=rollback) restart: unless-stopped + mem_limit: 512m # guardrail от runaway: snolla baseline ~100-200M; OOM в контейнере → restart:unless-stopped поднимет. standalone-compose → mem_limit (НЕ deploy.resources — то swarm-only). environment: NODE_ENV: production TZ: Europe/Moscow diff --git a/host-stacks/vds-kzntsv/labtools.compose.yml b/host-stacks/vds-kzntsv/labtools.compose.yml index aaf1e59..d4a40d6 100644 --- a/host-stacks/vds-kzntsv/labtools.compose.yml +++ b/host-stacks/vds-kzntsv/labtools.compose.yml @@ -26,6 +26,7 @@ services: container_name: labtools image: registry.kzntsv.site/labtools:566d41c # git-sha victor/labtools.ru master (snolla 0.42.1, bump 2026-07-05; prev 43e28ba=0.28.2=rollback) restart: unless-stopped + mem_limit: 512m # guardrail от runaway: snolla baseline ~100-200M; OOM в контейнере → restart:unless-stopped поднимет. standalone-compose → mem_limit (НЕ deploy.resources — то swarm-only). environment: NODE_ENV: production TZ: Europe/Moscow diff --git a/host-stacks/vds-kzntsv/tandemmebel.compose.yml b/host-stacks/vds-kzntsv/tandemmebel.compose.yml index 977ad2a..5710820 100644 --- a/host-stacks/vds-kzntsv/tandemmebel.compose.yml +++ b/host-stacks/vds-kzntsv/tandemmebel.compose.yml @@ -31,6 +31,7 @@ services: container_name: tandemmebel image: registry.kzntsv.site/tandemmebel:ed96b18 # git-sha victor/tandemmebel.ru master (snolla 0.42.0 / core 0.24.0 / data 0.14.1 — viewmodel-graph + blog-archive) restart: unless-stopped + mem_limit: 512m # guardrail от runaway: snolla baseline ~100-200M; OOM в контейнере → restart:unless-stopped поднимет. standalone-compose → mem_limit (НЕ deploy.resources — то swarm-only). environment: NODE_ENV: production TZ: Europe/Moscow