[2026-09-20] eagle: family/how-to/arr-stack-kraken.md family/how-to/kraken-watchtower.md family/how-to/openmediavault-rpi5.md personal/tech/docker-data-root-mount-race.md personal/tech/watchtower-docker-updates.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-20 19:04:33 +06:00
1 parent 4e656430ac
commit 71ccf6a456
5 files changed
+328 -1

No files matched your search

@@ -95,6 +95,8 @@ ssh kraken 'docker ps -q | wc -l' # ожидаем ~12, НЕ 0
> ⚠️ **Не путать с другим дефектом:** после этого reboot `jellyfin` поднялся, но отдавал **503** — это **отдельная** проблема (сервер старше БД, `no such column: p.Permission_Permissions_Guid`), НЕ связанная с гонкой монтирования. См. [[personal/tech/jellyfin-db-schema-mismatch]]. При диагностике «сервис не работает после reboot» различать: контейнер не поднялся (гонка) vs поднялся, но падает внутри (своя ошибка приложения).
> ℹ️ **Обновление 2026-09-20 (позже в тот же день):** `radarr` был **пересоздан** (переведён из общего проекта `docker` в свой `docker/radarr`, обновлён до 6.4.4) — см. [[family/how-to/arr-stack-kraken]]. `watchtower` сменил образ на `nickfedor/watchtower:1.22.2` — см. [[family/how-to/kraken-watchtower]]. Число контейнеров и их состав могли измениться; проверка `docker ps -q | wc -l` по-прежнему корректна как индикатор гонки, но ожидаемое число сверять заново.
## Крон не догоняет пропущенное окно
Общий питфолл для сервисов на этом узле: если Kraken лежал, cron-задачи (бэкап `0 4 * * *`, t610-подобные) **пропускаются без компенсации**. Для критичных — добавлять `@reboot`-строку с проверкой «артефакт за сегодня уже есть?».
+132
View File
@@ -0,0 +1,132 @@
---
title: Watchtower — почему не обновляет контейнеры
created: '2026-09-20'
updated: '2026-09-20'
type: tech
namespace: personal
tags: [watchtower, docker, updates, infra, pitfall]
related:
- "[[family/how-to/kraken-watchtower]]"
- "[[personal/tech/docker-data-root-mount-race]]"
- "[[personal/tech/jellyfin-db-schema-mismatch]]"
---
# Watchtower — почему не обновляет контейнеры
Реюзабельная теория. Живой разбор на Kraken — в [[family/how-to/kraken-watchtower]].
**Главный вывод: `docker ps` показывает `Up (healthy)` — это ничего не говорит о том, что Watchtower хоть раз что-то обновил.** Отсутствие обновлений не даёт ни ошибки, ни алерта. На Kraken Watchtower «работал» 2.5 месяца и не обновил ни один из 12 контейнеров.
## Четыре причины (проверять в этом порядке)
### 1. Не задан `--interval` → таймер сбрасывается каждым стартом
Без флага интервал = 24ч **от момента старта процесса**. Любой рестарт контейнера (reboot, `docker restart`, обновление самого Watchtower) обнуляет отсчёт. Если контейнер рестартуют чаще раза в сутки — **проверка не наступает никогда**.
Признак в логе:
```
level=info msg="Scheduling first run: ... in 23 hours, 59 minutes, 59 seconds"
level=info msg="Waiting for running update to be finished..."
```
Вторая строка — процесс проснулся, увидел незавершённый апдейт и **снова уснул**. Признак, что цикл заклинило.
**Фикс:** `--interval 86400` явно, либо `--schedule "0 0 4 * * *"` (cron-синтаксис из 6 полей), если нужен запуск в тихое время.
### 2. `DOCKER_API_VERSION` запинен на старую версию
`DOCKER_API_VERSION=1.40` в environment **ломает** чтение метаданных образа. Симптом:
```
level=info msg="Found new lscr.io/linuxserver/prowlarr:latest image (3e9bd62ca90c)"
level=info msg="Unable to update container \"/prowlarr\": no available image info. Proceeding to next."
```
Watchtower **нашёл** новый образ, но не может обновиться. В новых версиях API показывается сам: `using Docker API v1.54`.
**Фикс:** убрать `DOCKER_API_VERSION` из environment вообще. Watchtower сам согласует версию с dockerd.
### 3. Образ `containrrr/watchtower` не развивается
Last push `containrrr/watchtower` — **2023-11-11** (проверено Docker Hub API). Он несовместим с современным dockerd, отсюда и `no available image info` — это не только про API-версию.
**Фикс:** активный форк `nickfedor/watchtower` (актуальная версия 1.22.2, теги `latest`, `nightly`, semver).
```bash
# проверить дату образа
curl -s "https://hub.docker.com/v2/repositories/containrrr/watchtower/tags?page_size=5" \
| jq -r '.results[] | "\(.name) updated=\(.last_updated)"'
# проверить поддержку своей архитектуры (например arm64 для RPi)
curl -s "https://hub.docker.com/v2/repositories/nickfedor/watchtower/tags/1.22.2" \
| jq -r '.images[] | "\(.architecture) \(.os)"'
```
### 4. `--label-enable` без единого label → не обновит НИЧЕГО
С флагом `--label-enable` Watchtower трогает только контейнеры с label
`com.centurylinklabs.watchtower.enable=true`. Если label нет ни у кого — **сам по себе флаг делает Watchtower бесполезным**.
Проверка, кто помечен:
```bash
for c in $(docker ps --format "{{.Names}}"); do
echo "$c -> $(docker inspect $c -f '{{index .Config.Labels "com.centurylinklabs.watchtower.enable"}}')"
done
```
⚠️ `docker inspect` на контейнере без label вернёт **пустую строку**, а не «false» — не путать с `false` (явное отключение).
## Рабочий конфиг
```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
```
- `--interval 86400` — сутки, видно в логе рядом со `Next scheduled run`
- `--cleanup` — удалять старые образы; без него диск забивается (на Kraken 87%)
- `--label-enable` — оптин: обновляется только то, что явно помечено
## Проверка (обязательна)
`Up` + отсутствие ошибок ≠ работа. Нужен живой прогон:
```bash
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
nickfedor/watchtower:1.22.2 --run-once --monitor-only
```
`--monitor-only` обязателен, иначе `--run-once` **реально обновит** контейнеры.
Что должно быть в выводе:
```
level=info msg="Watchtower 1.22.2 using Docker API v1.54"
level=info msg="Found new image" container=<X> new_id=<...>
level=info msg="Update session completed" failed=0 scanned=N skipped=0 updated=0
```
`Found new image` = баг с метаданными вылечен. `updated=0` в monitor-only — нормально.
## ⚠️ Автообновление может сломать сервис: пинить мажор версии
Тип `latest` + автообновление = переход на новую **мажорную** версию без предупреждения. Для сервисов с миграциями БД (EF Core, Prisma, любые forward-only миграции) это необратимо:
- Jellyfin на Kraken: `latest` уехал 10.11.8 → 12.1, БД мигрировала вперёд, откатить схему нельзя → сервер отдавал **503**, `no such column: ...`. Детали: [[personal/tech/jellyfin-db-schema-mismatch]].
**Правило:** сервисам с БД и миграциями — пиновый тег (`image: jellyfin/jellyfin:12.1`), НЕ `latest` + watchtower. Либо не давать им label, либо сначала пин.
## Питфоллы диагностики
- `docker logs watchtower` — Watchtower пишет в **stdout**, в отличие от Jellyfin (тот пишет в файл). Смотреть логи легко.
- Таймстемпы в логе Watchtower — **UTC**, локальное время сервиса может быть другим.
- Единожды увиденный `Found new image` не значит, что обновление применилось — нужна следующая строка (`Unable to update` / `Updated`).
- Проверять надо **фактическую** дату запущенного образа, а не тег:
```bash
docker inspect <container> -f '{{index .Config.Labels "org.opencontainers.image.version"}}'
docker inspect <container> -f '{{index .Config.Labels "build_version"}}'
```
## Урок
Watchtower — компонент, который **молча не работает**. Его нельзя «поставить и забыть»: обязательны (а) явный `--interval`, (б) отсутствие `DOCKER_API_VERSION`, (в) периодический `--run-once --monitor-only` как health-check, (г) осознанное решение, каким контейнерам вообще разрешено автообновление.
## Связанные
- [[family/how-to/kraken-watchtower]] — живой разбор и точные команды на Kraken
- [[personal/tech/jellyfin-db-schema-mismatch]] — что ломает автообновление мажора
- [[personal/tech/docker-data-root-mount-race]] — другой дефект «контейнеры пропали»