MAATRIX / Блог / Сколько RAM нужно для Tandoor Recipes

Сколько RAM нужно для Tandoor Recipes

MAATRIX

Tandoor Recipes — самый функциональный self-hosted менеджер рецептов из тех, что реально ставят на VPS: он не просто хранит рецепты и собирает список покупок, а считает КБЖУ по ингредиентам, раскладывает блюда по меню и группирует рецепты в отдельные книги. Вся эта функциональность построена на Django и обязательном PostgreSQL, а не на лёгком стеке из FastAPI и SQLite, как у более простых аналогов, — и это прямо отражается на требованиях к памяти. Разберём, из чего складывается расход RAM у Tandoor и сколько закладывать под разные сценарии использования.

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

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

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

Что такое Tandoor Recipes и почему он тяжелее простых менеджеров

Tandoor (раньше проект назывался просто Recipes, отсюда имя Docker-образа vabene1111/recipes, сохранившееся до сих пор) — это Django-бэкенд с REST API и фронтенд на Vue.js. Из коробки он даёт заметно больше, чем базовый импорт рецептов по ссылке:

  • расчёт пищевой ценности (калории, белки, жиры, углеводы) по каждому ингредиенту и рецепту в целом;
  • книги рецептов — тематические подборки («Веганское», «Быстрые ужины», «На праздник»), которые можно расшарить отдельным пользователям;
  • планировщик меню на неделю/месяц с привязкой к календарю;
  • автогенерация списка покупок с группировкой по категориям и объединением одинаковых ингредиентов из разных рецептов;
  • пространства (spaces) — изолированные друг от друга наборы данных на одном инстансе, удобно для нескольких семей или небольшой команды на одном сервере;
  • гибкая система прав — кто может редактировать рецепты, кто только читать, кто управляет пространством.

Для сравнения: Mealie построен на FastAPI и по умолчанию работает на SQLite без отдельного процесса СУБД — это осознанно лёгкий стек, рассчитанный на то, чтобы завестись на минимальном VPS. Tandoor решает похожую задачу, но с прицелом на более серьёзную функциональность (нутрициология, книги, права доступа), и платит за это постоянно работающим PostgreSQL и более тяжёлым Django-бэкендом. Официально PostgreSQL — рекомендуемая и по факту единственная нормально поддерживаемая СУБД для продакшена; SQLite в документации упоминается скорее как вариант для быстрого локального теста, а не для постоянной эксплуатации.

Из чего складывается расход памяти

Реальный расход RAM на сервере с Tandoor — это сумма нескольких компонентов, и лучше сразу понимать вклад каждого, а не мерить «Tandoor целиком»:

  • Django + Gunicorn — сам бэкенд с REST API (Django REST Framework) поднимает несколько worker-процессов Gunicorn. Каждый воркер после прогрева (импорт всех Django-приложений, ORM-модели, DRF-сериализаторы) держит порядка 80-150 МБ — это ощутимо больше, чем у лёгких ASGI-приложений вроде FastAPI, из-за размера самого фреймворка и подключённых Django-модулей.
  • PostgreSQL — отдельный демон postgres, который в простое держит порядка 100-200 МБ вне зависимости от объёма архива рецептов, плюс 5-10 МБ на каждое активное соединение, если не настроен пул.
  • nginx (или встроенный веб-сервер образа) — раздача собранного Vue-фронтенда и статики/медиа (фото рецептов) занимает немного, 5-15 МБ базово.
  • Импорт рецепта по URL — при добавлении рецепта по ссылке Tandoor сам ходит на сайт-источник, скачивает страницу и парсит из неё ингредиенты, шаги и время готовки. На время одного такого запроса процесс кратковременно занимает больше памяти, чем при обычной отдаче страницы, — сопоставимо с тем, как это устроено у других self-hosted менеджеров рецептов с похожим импортом.
  • Работа с фото и книгами — генерация превью для фотографий рецептов и сборка книги из десятков позиций (с картинками и КБЖУ на каждой) — операции с более заметным, хоть и разовым, всплеском памяти, чем обычный просмотр списка рецептов.
  • ОС и системные службы — минимальный Ubuntu/Debian без графики занимает 100-200 МБ на ядро, systemd, cron, sshd.

Цифры выше — практический ориентир на основе типового поведения Django + Gunicorn + PostgreSQL, а не измеренный бенчмарк конкретной версии Tandoor: у вас может отличаться в зависимости от числа воркеров, размера архива рецептов и версии PostgreSQL. Относитесь к ним как к отправной точке для расчёта VPS, а не к гарантии.

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

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

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

Сколько RAM закладывать по сценариям

СценарийПространств (spaces)РецептовИмпорт по URLRAM VPSCPU
Личный архив, 1 человек1до 200-300иногда1,5 ГБ1 vCPU
Активное использование, семья1500-1500регулярно2 ГБ1-2 vCPU
Несколько семей/пространств на одном сервере2-4по 300-800 в каждомрегулярно2-4 ГБ2 vCPU
Небольшая команда/публичный инстанс5-15 пользователей2000+частый4 ГБ2-4 vCPU
Команда + другие сервисы на том же сервере15+2000+частый4-8 ГБ4 vCPU

Формально Tandoor запускается и на 1 ГБ RAM, но это без запаса: PostgreSQL уже сам по себе постоянно держит 100-200 МБ, Gunicorn с двумя воркерами — ещё 150-300 МБ, и на первом же массовом импорте архива рецептов или генерации нескольких превью подряд легко упереться в OOM. Для стабильной работы даже одиночного архива закладывайте от 1,5 ГБ — это тот случай, где экономия 500 МБ регулярно оборачивается перезапусками контейнера.

Число пространств (spaces) влияет на память меньше, чем кажется: это разделение на уровне данных в одной и той же базе, а не отдельные процессы приложения. Растёт в первую очередь объём БД и число одновременных пользователей, а не количество Gunicorn-воркеров — если, конечно, вы не поднимаете отдельный инстанс Tandoor на каждое пространство.

PostgreSQL — обязательный компонент: как не переплатить по памяти

В отличие от Wallabag или Mealie, где SQLite — рабочий вариант для личного использования, у Tandoor PostgreSQL по факту обязателен для нормальной эксплуатации. Это значит, что даже у одиночного пользователя с парой сотен рецептов на сервере всегда крутится полноценный демон СУБД — и его настройки по умолчанию рассчитаны не на VPS с 1-2 ГБ RAM, а на универсальный случай.

Официальный образ postgres в конфигурации по умолчанию не подстраивает shared_buffers и work_mem под маленький сервер. Для VPS с 1,5-2 ГБ RAM имеет смысл явно ограничить потребление через postgresql.conf (или переменные окружения соответствующего Docker-образа):

# postgresql.conf — под VPS с 1,5-2 ГБ RAM
shared_buffers = 128MB
work_mem = 4MB
maintenance_work_mem = 32MB
max_connections = 30

Меньше max_connections — меньше потенциальный пик по памяти на пиковой нагрузке (каждое соединение резервирует память под себя), а для одного Django-бэкенда с несколькими Gunicorn-воркерами 30 соединений — щедрый запас с учётом пула. Проверить реальное число активных соединений можно так:

docker exec -it db_recipes psql -U tandoor -d tandoor -c "SELECT count(*) FROM pg_stat_activity;"

Docker Compose и лимиты памяти

Официальная установка Tandoor через Docker Compose обычно состоит из двух ключевых сервисов — базы и самого приложения (фронтенд и бэкенд идут в одном образе, отдаются одним контейнером):

services:
  db_recipes:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: tandoor
      POSTGRES_USER: tandoor
      POSTGRES_PASSWORD: change_me
    volumes:
      - ./postgresql:/var/lib/postgresql/data
    deploy:
      resources:
        limits:
          memory: 300M
        reservations:
          memory: 150M

  web_recipes:
    image: vabene1111/recipes
    restart: unless-stopped
    env_file:
      - ./.env
    ports:
      - "8090:80"
    volumes:
      - ./staticfiles:/opt/recipes/staticfiles
      - ./mediafiles:/opt/recipes/mediafiles
      - ./nginx_config:/opt/recipes/nginx/conf.d
    depends_on:
      - db_recipes
    deploy:
      resources:
        limits:
          memory: 700M
        reservations:
          memory: 300M

В .env задаются SECRET_KEY, параметры подключения к БД (DB_ENGINE=django.db.backends.postgresql, POSTGRES_HOST=db_recipes и так далее) и число воркеров Gunicorn через GUNICORN_WORKERS — на VPS с 1,5-2 ГБ RAM разумно оставить 2, а не значение по умолчанию, рассчитанное на количество ядер сервера. С такой связкой закладывайте под весь стек от 1,5 ГБ, оставляя ОС и Docker-демону хотя бы 300-400 МБ сверху — сама контейнеризация добавляет накладные расходы поверх голых процессов. Если вы разворачиваете прод-окружение с нуля, общий порядок настройки Docker Compose (сети, restart-политики, лимиты) разобран в статье про пошаговую установку Docker Compose на Ubuntu 24.04, а сами принципы mem_limit/reservations — в материале про лимиты CPU и памяти в Docker.

КБЖУ, книги рецептов и импорт — где расход растёт

Из трёх «фирменных» функций Tandoor по-разному влияют на память:

Расчёт КБЖУ сам по себе дешёвый — это арифметика над числами, уже лежащими в базе (пищевая ценность ингредиента × вес по рецепту), а не отдельный тяжёлый процесс. Ощутимой нагрузки на память не создаёт даже при пересчёте по всему архиву рецептов разом.

Книги рецептов тяжелее, но тоже не критично: сборка книги — это выборка десятков записей из БД с подгрузкой превью фотографий и сериализацией через DRF. Чем больше рецептов в книге, тем заметнее кратковременный всплеск при открытии — на практике единицы-десятки лишних мегабайт на запрос, не более.

Импорт рецептов по URL — самая переменная по нагрузке операция. Каждый импорт — это отдельный HTTP-запрос к чужому сайту, разбор HTML и извлечение структурированных данных (ингредиенты, шаги, время). Если вы переносите архив из другого менеджера рецептов пачкой в несколько сотен ссылок, разумнее делать это порциями по 20-50 штук, а не одним скриптом на весь список сразу — так пиковая память остаётся предсказуемой.

Если после переноса на Tandoor старая система планирования VPS уже не устраивает по объёму, стоит заранее прикинуть запас — общий подход к тому, сколько памяти закладывать сверх голого расчёта, разобран в статье сколько оперативной памяти закладывать с запасом.

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

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

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

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

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

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

Хватит ли 1 ГБ RAM для Tandoor Recipes?

Формально запускается, но без запаса: PostgreSQL и Gunicorn вместе постоянно держат 300-500 МБ ещё до реальной нагрузки, и первый же массовый импорт рецептов рискует упереться в OOM. Для стабильной работы берите минимум 1,5 ГБ.

Можно ли обойтись без PostgreSQL, поставить SQLite?

Технически возможно для локального теста, но для постоянной эксплуатации официально рекомендуется и по факту нормально поддерживается только PostgreSQL — экономия на памяти здесь не стоит потери надёжности.

Чем Tandoor тяжелее Mealie по памяти?

В первую очередь обязательным PostgreSQL (100-200 МБ постоянно) и более тяжёлым Django-бэкендом по сравнению с лёгким FastAPI-стеком Mealie, который по умолчанию работает на SQLite вообще без отдельного процесса СУБД.

Сколько памяти реально добавляют КБЖУ и книги рецептов?

Немного — расчёт пищевой ценности почти ничего не стоит, сборка книги даёт лишь небольшой кратковременный всплеск на активный запрос. Основной расход у Tandoor формируют не эти функции, а сама архитектура (Django + PostgreSQL).

Как понять, чего не хватает — RAM или CPU?

Посмотрите docker stats --no-stream и free -h во время импорта рецептов или открытия тяжёлой книги: если растёт MEM USAGE контейнера web_recipes вплотную к лимиту — упираетесь в память, если контейнер стабилен по памяти, но растёт CPU % и растут задержки ответа — дело в процессоре, и здесь поможет уже другой материал про то, что делать при нехватке RAM, если симптомы совпадают.

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

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

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