MAATRIX / Блог / Renovate в Docker Compose: готовый файл

Renovate в Docker Compose: готовый файл

MAATRIX

Зависимости в проекте устаревают тихо: сегодня библиотека на минорной версии позади, через полгода — на трёх мажорных, и обновление превращается в отдельный спринт с непредсказуемым риском. Renovate закрывает эту проблему автоматически: он сканирует репозитории по расписанию и открывает pull request на каждое обновление — вам остаётся смотреть CI и жать «мёрж». Ниже — рабочий docker-compose.yml для self-hosted Gitea, GitLab CE и Forgejo, без привязки к SaaS-версии Renovate.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Renovate против Dependabot и Watchtower: что именно он делает

Renovate — это CLI-инструмент, который клонирует репозиторий, читает манифесты зависимостей (package.json, go.mod, requirements.txt, Dockerfile, docker-compose.yml и десятки других форматов) и создаёт PR с обновлением версии, обновлённым лок-файлом и changelog в описании. Он не запускает и не перезапускает ваши сервисы — этим занимается CI/CD после мёржа.

Важно не путать его с двумя соседними инструментами:

  • Watchtower обновляет уже запущенные Docker-контейнеры на новый образ прямо на сервере, без PR и без ревью — грубее, но проще. Если вам нужен именно такой сценарий, у нас есть отдельный разбор — автообновление Watchtower на VPS.
  • Dependabot — облачный сервис GitHub, который на self-hosted Gitea/GitLab/Forgejo не работает вообще. Renovate — по сути открытая альтернатива, которая одинаково хорошо живёт и в облаке, и на своём сервере.

Renovate не демон: контейнер стартует, делает один проход по всем репозиториям, открывает/обновляет PR и завершается с кодом 0. Расписание вы задаёте либо через cron на хосте, либо через schedule в конфиге самого Renovate (это разные вещи, и путать их — частая причина «почему Renovate не запускается ночью»).

Готовый docker-compose.yml

Структура проекта:

renovate/
├── docker-compose.yml
├── .env
└── config.js

docker-compose.yml:

services:
  renovate:
    image: ghcr.io/renovatebot/renovate:latest
    container_name: renovate
    restart: "no"
    env_file:
      - .env
    volumes:
      - ./config.js:/usr/src/app/config.js:ro
      - renovate-cache:/tmp/renovate/cache
    # можно передать список репозиториев прямо аргументом,
    # если не хотите прописывать его в config.js
    # command: ["group/repo-1", "group/repo-2"]

volumes:
  renovate-cache:

ghcr.io/renovatebot/renovate:latest тянет актуальный мажорный релиз — для прод-контура лучше зафиксировать конкретный тег (например, renovate:39), который вы сами проверили на ghcr.io/renovatebot/renovate/tags, чтобы обновление образа не подменило поведение конфига без вашего ведома.

.env:

RENOVATE_TOKEN=ваш_токен_с_правами_на_репозитории
RENOVATE_PLATFORM=gitea
RENOVATE_ENDPOINT=https://git.example.com/api/v1
LOG_LEVEL=info

renovate-cache — именованный том под кеш пакетных менеджеров (npm, go modules, pip). Без него каждый запуск заново тянет метаданные из реестров, и на большом монорепо это заметно увеличивает время прохода.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

config.js: репозитории, расписание, правила автомёржа

Renovate поддерживает конфиг в JSON, JSON5 и JS — последний удобнее, потому что можно писать комментарии. Базовый пример под self-hosted Gitea:

module.exports = {
  platform: 'gitea',
  endpoint: 'https://git.example.com/api/v1',
  autodiscover: false,
  repositories: ['team/backend', 'team/frontend', 'team/infra'],

  onboarding: true,
  onboardingConfig: {
    extends: ['config:recommended'],
  },

  timezone: 'Europe/Moscow',
  schedule: ['after 2am and before 5am every weekday'],

  labels: ['dependencies'],
  prConcurrentLimit: 10,
  prHourlyLimit: 5,

  packageRules: [
    {
      matchUpdateTypes: ['minor', 'patch'],
      automerge: true,
      automergeType: 'branch',
    },
    {
      matchUpdateTypes: ['major'],
      automerge: false,
      addLabels: ['major-update'],
    },
    {
      matchPackagePatterns: ['^eslint'],
      groupName: 'eslint',
    },
  ],
};

Ключевые поля:

  • repositories — список репозиториев в формате owner/repo. Без него нужен autodiscover: true, но тогда Renovate обойдёт вообще все репозитории, куда у токена есть доступ — на большом инстансе это долго и не всегда то, что нужно.
  • onboarding — при первом запуске на новом репозитории Renovate вместо обычного PR откроет «onboarding PR» с предложенным renovate.json. Пока его не смёржат, реальные обновления не начнутся — это осознанное поведение, не баг.
  • schedule внутри config.js — это НЕ расписание запуска контейнера, а окно, в которое Renovate разрешено *создавать и обновлять* PR. Сам процесс должен быть запущен извне (см. следующий раздел), а schedule лишь фильтрует, что делать в рамках этого запуска.
  • packageRules — точечная настройка: где включить автомёрж без ревью (обычно patch/minor с проходящим CI), а где оставить major-обновления на ручную проверку.

Запуск по расписанию: cron на хосте vs sidecar-контейнер

Раз Renovate завершается после одного прохода, планировщик нужен снаружи. Два рабочих варианта.

Вариант 1 — cron на хосте (проще, рекомендуется для одиночного VPS):

crontab -e
0 3 * * 1-5 cd /opt/renovate && docker compose run --rm renovate >> /var/log/renovate.log 2>&1

Так контейнер поднимается раз в будни в 3:00, делает проход, пишет лог и удаляется (--rm), не оставляя мёртвых контейнеров в docker ps -a. Если crontab на сервере для вас в новинку — у нас есть отдельный разбор настройки cron-задач на VPS.

Вариант 2 — sidecar-контейнер с доступом к Docker socket (когда хочется держать всё в compose, без правки хостового crontab):

services:
  renovate:
    image: ghcr.io/renovatebot/renovate:latest
    container_name: renovate
    restart: "no"
    profiles: ["manual"]
    env_file:
      - .env
    volumes:
      - ./config.js:/usr/src/app/config.js:ro
      - renovate-cache:/tmp/renovate/cache

  scheduler:
    image: mcuadros/ofelia:latest
    container_name: renovate-scheduler
    restart: unless-stopped
    depends_on:
      - renovate
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    command: daemon --docker
    labels:
      ofelia.job-run.renovate.schedule: "0 0 3 * * 1-5"
      ofelia.job-run.renovate.container: "renovate"

volumes:
  renovate-cache:

Ofelia сам дёргает контейнер renovate по cron-выражению через Docker API. Плюс в том, что вся конфигурация живёт в одном compose-проекте и переезжает вместе с ним; минус — лишний постоянно работающий процесс с доступом к docker.sock, а это уже вопрос поверхности атаки, если сервер разделяют несколько сервисов. Для одного проекта на выделенном VPS хостовый cron честнее и проще в отладке.

Токен и подключение к self-hosted Gitea, GitLab CE, Forgejo

Renovate обращается к API вашего git-сервера, поэтому нужен персональный токен с правом читать и писать репозитории и открывать PR/MR.

Gitea / Forgejo: *Настройки профиля → Приложения → Создать новый токен*, права минимум repository (read/write) и misc для веб-хуков, если планируете их использовать. Значение RENOVATE_PLATFORMgitea; для Forgejo на актуальных версиях Renovate тоже подходит platform: gitea совместимого режима, но если у вас свежий Forgejo и свежий Renovate, стоит проверить в официальной документации, добавлена ли отдельная платформа forgejo в вашей версии — это менялось от релиза к релизу. Если держите Forgejo, у нас есть готовый файл для самого сервиса — Forgejo в Docker Compose.

GitLab CE: *User Settings → Access Tokens*, scope — api. RENOVATE_PLATFORM=gitlab, RENOVATE_ENDPOINT указывает на https://git.example.com/api/v4. Если GitLab CE у вас ещё не поднят и есть вопросы по интеграции с CI — см. настройку GitLab CI/CD на VPS.

Токен — секрет с широкими правами на весь git-сервер, поэтому его нельзя коммитить в репозиторий вместе с config.js. Держите его только в .env, добавьте .env в .gitignore, а на проде рассмотрите более строгое хранение секретов — этому посвящена отдельная статья про управление паролями через Docker secrets.

Ресурсы сервера и первый запуск

Renovate на каждый репозиторий делает полный или частичный git clone, разворачивает lock-файлы и обращается к реестрам пакетов (npm, PyPI, Go proxy, Docker Hub) — это кратковременно, но заметно нагружает CPU и сеть на время прохода, особенно на монорепо с десятками package.json. Для 5–10 средних репозиториев обычно достаточно 2 vCPU и 2–4 ГБ RAM; если Renovate живёт на том же VPS, что и сам git-сервер (Gitea/GitLab CE) плюс CI-раннер, закладывайте запас — GitLab CE сам по себе прожорлив по памяти.

Первый запуск стоит сделать вручную, не через cron, чтобы сразу видеть логи:

cd /opt/renovate
docker compose run --rm renovate

В логе ищите строки вида Repository started для каждого репозитория и итоговую сводку Renovate finished. Если onboarding: true, ждите не обновления зависимостей, а onboarding PR с предложенным конфигом — это нормально, обновления начнутся после его мёржа.

Частые ошибки при первом запуске

Симптом в логеПричинаЧто проверить
Response code 401 (Unauthorized)Токен не тот или без нужных правПересоздать токен с правами repository/api, обновить .env
Response code 404 при обращении к endpointНеверный путь APIДля Gitea/Forgejo — /api/v1, для GitLab — /api/v4
connect ECONNREFUSEDEndpoint указывает не туда (внутренний хост вместо внешнего, или наоборот)Из контейнера renovate endpoint должен быть доступен так же, как из браузера, если контейнер не в одной docker-сети с git-сервером
Репозитории просканированы, но PR не появилисьschedule не разрешает запись в текущее время, либо всё уже up-to-dateВременно убрать schedule из config.js для теста, посмотреть dryRun в логах
Onboarding PR висит без обновленийonboarding: true и никто не смёржил предложенный конфигСмёржить onboarding PR или явно передать onboarding: false, если конфиг уже задан вручную
EACCES при работе с кешемТом renovate-cache создан с правами root, а процесс в контейнере работает не от rootПересоздать том: docker volume rm renovate_renovate-cache и запустить заново

Если контейнер вообще не поднимается — стоит свериться с общим чек-листом по докеру: контейнер не запускается — причины и решение.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Чем Renovate лучше, чем просто вручную раз в месяц смотреть npm outdated?

Он не даёт зависимостям накапливаться: каждое обновление приходит отдельным PR с CI-проверкой сразу, пока diff маленький и причину падения теста легко найти. Ручной разбор десятков накопившихся обновлений за раз — куда более рискованная и долгая операция.

Можно ли доверить Renovate автомёрж без ревью?

Да, но избирательно — через packageRules с matchUpdateTypes: ['patch', 'minor'] и automerge: true, обязательно при условии зелёного CI (platformAutomerge учитывает статус проверок). Major-обновления лучше оставлять на ручной мёрж — они чаще ломают API.

Нужен ли отдельный VPS под Renovate или можно на сервере с Gitea/GitLab?

Можно на том же сервере — Renovate нагружает его только на время прохода (обычно минуты), а не постоянно, в отличие от самого git-сервера или CI-раннеров.

Как часто нужно запускать Renovate?

Для активных репозиториев — раз в сутки ночью; для спокойных проектов достаточно раз в неделю. Слишком частый запуск не даёт выигрыша, а лишь чаще упирается в prHourlyLimit и создаёт шум в списке PR.

Renovate работает с приватными npm/PyPI-реестрами?

Да, через hostRules в config.js с токеном доступа к конкретному реестру — механизм отдельный от RENOVATE_TOKEN git-платформы.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →