Как Watchtower сломал мне сервис в три часа ночи

Долгое время у меня в стеке крутился Watchtower — штука, которая сама следит за обновлениями образов и тихо подтягивает новые версии. Идея красивая: ты ничего не делаешь, а контейнеры всегда свежие. На практике эта красота однажды разбудила меня в три часа ночи уведомлением «сервис недоступен».

Что произошло. У одного из контейнеров вышел новый тег latest, и это была мажорная версия — со сменой формата конфига и схемы базы. Watchtower честно сделал свою работу: выкачал новый образ, снёс старый контейнер, поднял новый. Новый стартанул, увидел старый конфиг, не понял его и упал. И так по кругу — рестарт, падение, рестарт. К утру лог был размером с небольшую книгу.

Сам виноват, конечно. latest — это не версия, это лотерея. Ты подписываешься на «что разработчик зальёт следующим», а он может залить что угодно.

После этого Watchtower я выключил. Совсем:

docker compose -f /app/watchtower/docker-compose.yml down

Теперь обновляюсь руками и осознанно. Во-первых, везде прибил конкретные теги вместо latest:

services:
  paperless:
    # было: image: paperlessngx/paperless-ngx:latest
    image: paperlessngx/paperless-ngx:2.14.7

Во-вторых, завёл простой ритуал. Раз в пару недель смотрю, что вышло:

# что вообще доступно
docker compose -f /app/<сервис>/docker-compose.yml pull --dry-run

# а потом обязательно читаю changelog/release notes на гитхабе

И только если в release notes нет слов про «breaking changes», «migration» и «backup your data before upgrade» — обновляюсь. А если есть — сначала делаю бэкап томов, потом обновляю, потом проверяю, что всё живо.

# бэкап перед апгрейдом — стало рефлексом
docker run --rm -v paperless_data:/data -v $(pwd):/backup \
  alpine tar czf /backup/paperless_data_$(date +%F).tar.gz -C /data .

Да, это медленнее. Да, иногда я неделю сижу на «старой» версии. Зато я точно знаю, что именно и когда поменялось, и если что-то сломается — это будет в удобное мне время, а не в 3:00 под аккомпанемент пуш-уведомлений.

Автоматизация хороша ровно до того момента, пока она не автоматизирует катастрофу. Обновление сервисов — как раз тот случай, где я предпочитаю держать руку на рубильнике сам.