Files
obsidian-vault/family/how-to/kraken-watchtower.md
T

263 lines
17 KiB
Markdown
Executable File
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.
---
updated: '2026-09-27'
title: Watchtower — Kraken
created: '2026-09-20'
type: tech
namespace: family
tags:
- watchtower
- docker
- updates
- infra
- kraken
- pitfall
related:
- '[[family/how-to/arr-stack-kraken]]'
- '[[personal/tech/watchtower-docker-updates]]'
- '[[personal/tech/jellyfin-db-schema-mismatch]]'
- '[[personal/tech/docker-data-root-mount-race]]'
- '[[personal/tech/kraken-docker-startup-order]]'
---
# Watchtower на Kraken (RPi5 / OMV / arm64)
> **Создано:** 2026-09-20. **Обновлено:** 2026-09-27.
> 🟡 **Статус 2026-09-27:** фикс 2026-09-20 **не был применён** (контейнер не пересоздан,
> крутился `containrrr/watchtower` без флагов). **Пересоздан 2026-09-27** на `nickfedor/watchtower:1.22.2`
> + критичные контейнеры исключены меткой `enable=false`. Подробно — § «ОПРОВЕРГНУТО» ниже.
> **Связанные:** [[family/how-to/arr-stack-kraken]], [[personal/tech/watchtower-docker-updates]] (реюзабельная теория), [[personal/tech/jellyfin-db-schema-mismatch]], [[personal/tech/docker-data-root-mount-race]], [[personal/tech/kraken-docker-startup-order]]
## ✅ РЕШЕНИЕ (2026-09-20): какие контейнеры обновляются автоматом
Решение Alex: «вариант 1 + jellyfin, portainer, transmission». Итого **7 контейнеров размечены** label `com.centurylinklabs.watchtower.enable=true`:
| Контейнер | Где label | Примечание |
|---|---|---|
| `radarr` | `docker/radarr/docker-compose.yml` | |
| `sonarr` | `docker/sonarr/docker-compose.yml` | |
| `prowlarr` | `docker/prowlarr/docker-compose.yml` | |
| `flaresolverr` | `docker/prowlarr/docker-compose.yml` | тот же файл |
| `jellyfin` | `docker/jellyfin/docker-compose.yml` | ⚠️ тег `latest` — см. ниже |
| `portainer` | `docker/portainer/docker-compose.yml` | данные в `/data`, пересоздание безопасно |
| `transmission` | `docker/transmission/docker-compose.yml` | 244 торрента в `./` (config), пересоздание данные не задело |
**НЕ размечены (сознательно):**
- `watchtower` — сам себя (иначе зацикливание)
- `hermes-kraken` — агент Hermes
- `xray-reverse-bridge` — VPN-мост
- `rclone`, `cloudflared`
Проверка после простановки:
```bash
sudo docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
nickfedor/watchtower:1.22.2 --run-once --monitor-only --label-enable
# → Update session completed failed=0 scanned=7 updated=0 ← ровно 7, не 13
```
### Про Jellyfin и тег (решение Alex)
Алекс явно потребовал: **«пусть ставит до всех публичных релизов»** → стоит `image: jellyfin/jellyfin:latest`, Watchtower поставит в т.ч. мажор 13.
Моя рекомендация была пинить `12` (после инцидента `jellyfin-db-schema-mismatch`, где контейнер остался на старом образе при уже мигрированной БД и отдавал 503). **Алекс выбрал `latest` — риск принят осознанно.** Если Jellyfin однажды отдаст 503 после автообновления — смотреть [[personal/tech/jellyfin-db-schema-mismatch]], бэкап БД: `/home/kraken/backups/jellyfin-label-20260920-190935/`.
⚠️ Важное следствие `--cleanup`: старые образы удаляются, откатиться на предыдущую версию после автообновления будет **некуда**.
## Что было сломано (2026-09-20)
Watchtower стоял на `containrrr/watchtower` **без единого флага** и **не обновил ни один контейнер за ~2.5 месяца**.
Четыре независимые причины:
| # | Причина | Как выглядело в логе |
|---|---|---|
| 1 | Не задан `--interval` | `Scheduling first run: ... in 23 hours 59 minutes` — каждый рестарт контейнера сбрасывал таймер, а рестарты были |
| 2 | `DOCKER_API_VERSION=1.40` (старый API) | `Unable to update container "/prowlarr": no available image info` |
| 3 | Образ `containrrr/watchtower` мёртв | last push **2023-11-11** (проверено через Docker Hub API) |
| 4 | Нет label на целевых контейнерах | `Scanned=12 Updated=0` |
Итог до фикса: `Session done Failed=0 Scanned=12 Updated=0`, а единственная попытка обновления упала с `no available image info`.
## Фикс (ВЫПОЛНЕН 2026-09-20)
`containrrr/watchtower` → **`nickfedor/watchtower:1.22.2`** (активный форк; у containrrr последний push 2023-11-11).
```bash
D=/srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/docker/watchtower
sudo cp $D/docker-compose.yml /home/kraken/arr-fix-backup-20260920/watchtower-compose.bak
cd $D && sudo docker compose pull watchtower && sudo docker compose up -d watchtower
```
Compose (`docker/watchtower/docker-compose.yml`):
```yaml
services:
watchtower:
image: nickfedor/watchtower:1.22.2
container_name: watchtower
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 86400 --cleanup --label-enable
# DOCKER_API_VERSION=1.40 УДАЛЁН — именно он ломал обновление
```
Флаги:
- `--interval 86400` — явные 24ч (без флага таймер сбрасывался каждым стартом)
- `--cleanup` — удалять старые образы (диск на 87%, иначе забьёт)
- `--label-enable` — обновлять ТОЛЬКО контейнеры с label `com.centurylinklabs.watchtower.enable=true`
## Проверка (обязательна — «запущено» ≠ «работает»)
```bash
# 1) версия и API
sudo docker logs --tail 20 watchtower
# → Watchtower 1.22.2 using Docker API v1.54 (был v1.40)
# → Next scheduled run: ... in 23 hours 59 minutes ← таймер виДЕН
# 2) РЕАЛЬНЫЙ прогон без изменений — БЕЗ label (сравнение)
sudo docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
nickfedor/watchtower:1.22.2 --run-once --monitor-only
# → Update session completed failed=0 scanned=13 updated=0
# → "Found new image" container=transmission ← баг no-available-image-info ВЫЛЕЧЕН
# 3) С label (актуальный режим) → должно быть ровно 7
sudo docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
nickfedor/watchtower:1.22.2 --run-once --monitor-only --label-enable
# → Update session completed failed=0 scanned=7 updated=0
```
## ⚠️ КРИТИЧНО: Watchtower и Jellyfin — история и принятое решение
**Watchtower уже один раз сломал Jellyfin** (см. [[personal/tech/jellyfin-db-schema-mismatch]]): контейнер остался на старом образе 10.11.8 при уже мигрированной до 12.1 БД → `no such column: p.Permission_Permissions_Guid` → 503.
Разбор инцидента показывает: **сама миграция БД прошла нормально**, упало из-за рассинхрона «старый сервер + новая схема». То есть мажорный апдейт сам по себе БД не ломает.
**Решение Alex (2026-09-20):** тег `latest`, обновляемся до всех публичных релизов, включая мажор 13. Риск принят осознанно. Бэкап БД перед пересозданием: `/home/kraken/backups/jellyfin-label-20260920-190935/` (24 МБ).
**Если Jellyfin отдаёт 503 после автообновления** — это тот же класс проблемы: смотреть `personal/tech/jellyfin-db-schema-mismatch`, проверить `docker exec jellyfin /jellyfin/jellyfin --version` против версии в `__EFMigrationsHistory`.
⚠️ Следствие `--cleanup`: старые образы удаляются, откат на предыдущую версию **после** автообновления невозможен. Если нужен откат — только полный restore БД из бэкапа.
## Диагностика Watchtower
```bash
sudo docker ps --format "{{.Names}}\t{{.Image}}\t{{.Status}}" | grep watchtower
sudo docker logs --tail 40 watchtower
# кто помечен для автообновления:
for c in $(sudo docker ps --format "{{.Names}}"); do
echo "$c -> $(sudo docker inspect $c -f '{{index .Config.Labels "com.centurylinklabs.watchtower.enable"}}')"
done
```
Грабли:
- `Unable to update container: no available image info` — старый `DOCKER_API_VERSION`, либо несовместимость containrrr-версии с новым dockerd.
- **Рестарт контейнера сбрасывает таймер** — без `--interval` это делает Watchtower бесполезным.
- `--run-once` **нельзя** запускать без `--monitor-only`, если не хочешь реальных обновлений.
- Watchtower пишет в stdout (`docker logs`), в отличие от Jellyfin.
## Бэкап
`/home/kraken/arr-fix-backup-20260920/watchtower-compose.bak` + остальные бэкапы в той же папке:
- `radarr-config-preupgrade.tar.gz` (58M), `sonarr-config-preupgrade.tar.gz` (20M), `prowlarr-config-preupgrade.tar.gz` (3.9M)
- `prowlarr.db.bak`, `watchtower-compose.bak`, `networks.txt`, 4× `<container>-inspect.json`, 3× compose-файла
## 🔴 ОПРОВЕРГНУТО 2026-09-27: фикс 2026-09-20 НЕ БЫЛ ПРИМЕНЁН
**Запись «Фикс ВЫПОЛНЕН 2026-09-20» выше — неверна.** Проверка 2026-09-27 показала:
```
$ docker inspect watchtower --format '{{.Config.Image}} | Created:{{.Created}}'
containrrr/watchtower | Created:2026-05-12T15:10:55Z
$ docker inspect watchtower --format '{{.Config.Cmd}}'
[] ← БЕЗ ФЛАГОВ
```
**Что произошло:** compose-файл действительно был исправлен 2026-09-20 (образ `nickfedor/watchtower:1.22.2`,
флаги `--interval 86400 --cleanup --label-enable`), но **контейнер не был пересоздан**. Создан он
2026-05-12 и с тех пор не менялся. `docker compose up -d watchtower` **не отработал** —
либо не выполнился, либо выполнился не в той директории.
**Почему проверка это не поймала:** прогон, записанный как доказательство (`scanned=7 failed=0`),
шёл через `docker run --rm ... nickfedor/watchtower:1.22.2`. Это **временный контейнер из нужного
образа** — он подтверждает, что образ рабочий, но **ничего не говорит о работающем контейнере**.
Боевой `watchtower` продолжал крутить `containrrr/watchtower` без `--label-enable`.
🔴 **Урок (общий):** `docker run --rm <образ>` проверяет **образ**, а не **работающий контейнер**.
Проверять надо `docker inspect` самого контейнера — образ, `Cmd`, дату создания. Если дата создания
старше правки compose-файла, правка не применена.
🔴 **Урок (общий):** «поправил compose» ≠ «применил». Compose-файл — декларация; пока не выполнен
`docker compose up -d`, работающая конфигурация не меняется. Симптом-маркер: метка/флаг виден в файле,
но не в `docker inspect`.
### Что реально сделано 2026-09-27
1. Бэкап: `/home/kraken/_backup-compose-20260927/` (`mattermost.yml`, `balda.yml`, `obsidian-mcp.yml`, `watchtower-active.yml`).
2. Метка `com.centurylinklabs.watchtower.enable: "false"` добавлена в compose четырёх критичных сервисов:
`mm-postgres`, `mattermost` (`/home/kraken/mattermost/docker-compose.yml`),
`balda-mm` (`/home/kraken/balda/docker-compose.yml`),
`obsidian-mcp` (`/home/kraken/obsidian-mcp/docker-compose.yml`).
3. **Watchtower пересоздан** из `/srv/.../docker/watchtower/` — впервые с 2026-05-12:
```bash
cd /srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/docker/watchtower
sudo docker compose up -d
# Image: nickfedor/watchtower:1.22.2
# Cmd: [--interval 86400 --cleanup --label-enable]
```
4. Контейнеры пересозданы (`docker compose up -d` в каждом проекте) — **метка применяется только
при создании контейнера**.
### 🔴 `docker update --label-add` НЕ СУЩЕСТВУЕТ
Метки (`labels`) в Docker **нельзя изменить у работающего контейнера**. Попытка:
```bash
docker update --label-add com.centurylinklabs.watchtower.enable=false mm-postgres
# → unknown flag: --label-add
```
Единственный путь — правка compose + пересоздание. Это важно: старая идея «проставить метку
командой без пересоздания» **нереализуема**.
### Результат (проверено 2026-09-27)
| Контейнер | Метка watchtower.enable | Статус |
|---|---|---|
| `mm-postgres` | `false` | running, healthy |
| `mattermost` | `false` | running, healthy |
| `balda-mm` | `false` | running |
| `obsidian-mcp` | `false` | running |
Watchtower: `nickfedor/watchtower:1.22.2`, `--interval 86400 --cleanup --label-enable`,
`Next scheduled run: ... in 23 hours 59 minutes 59 seconds`.
### Следствие: Watchtower УБИВАЛ контейнеры
Старый Watchtower без `--label-enable` лез во **все** контейнеры и гасил их SIGTERM→SIGKILL.
На `mm-postgres` это выглядело как:
```
16:25:42 container kill signal=2 ← SIGTERM
16:25:54 container kill signal=9 ← SIGKILL (пауза 11.6 с = таймаут docker stop)
16:25:58 container die exitCode=137, execDuration=70
```
`exitCode=137` = 128 + 9 (SIGKILL). **Не OOM** — `dmesg`/`journalctl -k` пусты, RAM available 2540 МБ.
Разбор: [[personal/tech/kraken-docker-startup-order]].
⚠️ `restart: unless-stopped` **не защищает** — Watchtower работает вне политик рестарта: он сам
останавливает контейнер, чтобы пересоздать его с новым образом.
### Что дальше (открытые пункты)
| # | Пункт | Статус |
|---|---|---|
| 1 | `Allowed Hosts is not configured` warning в Radarr/Sonarr/Prowlarr — ограничить, какие hostname могут обращаться | ⏳ отдельная задача |
| 2 | Home Assistant на Kraken — `Exited (128)` ~2 месяца, не поднимался (см. [[family/how-to/kraken-access]]) | ⏳ отдельная задача |
| 3 | `/home/kraken/watchtower/` — директории нет; метка старого контейнера ссылалась на удалённый файл. **Проверить, нужна ли чистка метаданных** | ⏳ |
| 4 | `/home/kraken/_backup-compose-20260927/` — удалить после проверки Alex | ⏳ |
| 5 | ⚠️ Проверить поведение при **ребуте хоста** — соблюдается ли порядок между проектами при загрузке | ⏳ |
✅ Закрыто 2026-09-20 (частично): label проставлены на 7 контейнеров.
✅ Закрыто 2026-09-27: Watchtower **реально** пересоздан, критичные контейнеры исключены меткой.
🔴 Открыто: правка 2026-09-20 не была применена — **проверять `docker inspect`, а не файл**.
## Теория (реюзабельно)
Общие причины «Watchtower не обновляет» без привязки к Kraken — [[personal/tech/watchtower-docker-updates]].