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

17 KiB
Executable File
Raw Blame History

updated, title, created, type, namespace, tags, related
updated title created type namespace tags related
2026-09-27 Watchtower — Kraken 2026-09-20 tech family
watchtower
docker
updates
infra
kraken
pitfall
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

✅ РЕШЕНИЕ (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

Проверка после простановки:

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).

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):

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

Проверка (обязательна — «запущено» ≠ «работает»)

# 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

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:
    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 нельзя изменить у работающего контейнера. Попытка:

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.