Перейти к основному содержимому

Когда нужен runtime

Большинство фронтенд-проектов — статика: после npm run build получается папка с HTML/JS/CSS, и её достаточно положить в хранилище. Это самый быстрый и самый дешёвый режим Layero.

Но некоторые приложения нельзя превратить в SPA — им нужен процесс на сервере:

  • SSR Next.js без output: 'export',
  • Node-сервер — Express, NestJS, Fastify и любой другой, слушающий порт,
  • Python-приложение — Django, FastAPI, Flask и любое WSGI/ASGI,
  • Streamlit / Gradio — Python-приложения с веб-интерфейсом.

Для них Layero запускает пользовательский контейнер.

Поддерживаемые пресеты​

project_typeЧто это
spaСтатика (по умолчанию).
ssr_nextNext.js с SSR или API-роутами.
node_webЛюбой Node-сервер, слушающий HTTP: Express, Fastify, NestJS, Koa, Hono и другие.
python_webЛюбое WSGI/ASGI-приложение: Django, FastAPI, Flask, Starlette, Litestar и другие.
streamlitStreamlit-приложение (нужен app.py).
gradioGradio-приложение (нужен app.py).

flask — устаревшее имя, оставленное для совместимости: это алиас python_web. Новые проекты получают python_web.

Для каждого пресета используется готовый Dockerfile-шаблон — свой образ собирать не нужно.

Как задать тип вручную​

Обычно не нужно: тип определяется сам (см. ниже). Если Layero принял сервер за статический сайт, способов три:

  • layero.json в репозитории — значение едет вместе с кодом:

    layero.json
    { "runtime": "node_web", "startCommand": "node dist/server.js", "port": 3000 }

    Все ключи — на странице layero.json.

  • Флаг CLI — разово, без файла: npx layero@latest deploy -t node_web (или -t python_web, -t ssr_next).

  • Панель — Project → Runtime type.

Что нужно от приложения​

  • Команда запуска. У Node-приложения Layero берёт скрипт start из package.json. Скрипта start нет — задайте startCommand. Пути в команде отсчитываются от /app, и файл должен существовать после сборки.
  • Адрес и порт. Приложение слушает 0.0.0.0 и порт из переменной $PORT: uvicorn main:app --host 0.0.0.0 --port $PORT. Сервер на 127.0.0.1 снаружи контейнера недоступен, и запуск упадёт. Приложение слушает свой порт — укажите его в port.
  • Ответ на GET /. Проверка запуска ждёт ответа без 5xx. Бот на long-polling без HTTP-сервера её не пройдёт.

После события ready первый запрос может до минуты получать заглушку 404, пока контейнер стартует. 404, который держится дольше минуты, — настоящий отказ: смотрите npx layero@latest logs --runtime.

Что платформа добавляет к Python-приложению​

Образ python_web сначала ставит зависимости из requirements.txt (или выполняет вашу команду установки — installCommand в layero.json), а затем отдельным шагом добавляет gunicorn>=21.2 и uvicorn[standard]>=0.30. Поэтому в логе сборки видна их установка, даже если в requirements.txt их нет. Это не ошибка: на них работают команды запуска по умолчанию.

ПриложениеКоманда запуска по умолчанию
ASGI (FastAPI, Starlette и др.)uvicorn main:app --host 0.0.0.0 --port $PORT
WSGI (Flask и др.)gunicorn main:app --bind 0.0.0.0:$PORT; число воркеров зависит от памяти инстанса
Djangouvicorn <проект>.asgi:application … или gunicorn <проект>.wsgi:application …

Вместо main подставляется первый найденный модуль из списка main, app, application, server, asgi, wsgi. aiohttp и Tornado запускаются как python main.py, Sanic — своим сервером. Свою команду задают через startCommand в layero.json. Серверы при этом всё равно ставятся, и своя команда установки их тоже не убирает. Если в requirements.txt закреплена версия gunicorn или uvicorn ниже этих минимумов, сборка поставит более новую. Streamlit и Gradio запускаются своими серверами, и к ним gunicorn и uvicorn не добавляются.

Что определяется автоматически​

Тип угадывается по зависимостям — руками выбирать обычно не нужно.

Python → python_web. Фреймворки: Django, FastAPI, Flask, Starlette, Litestar, Quart, Sanic, BlackSheep, Falcon, Bottle, Pyramid, CherryPy, aiohttp, Tornado. Серверы: Uvicorn, Gunicorn, Hypercorn, Daphne. Точка входа ищется в app.py, main.py или manage.py.

Node → node_web. Express, Fastify, Koa, NestJS, Hapi, Hono, AdonisJS, Restify, Polka, Feathers, Sails, h3, Elysia, json-server.

Если вашего фреймворка в списке нет, но приложение слушает HTTP-порт — оно всё равно запустится: задайте node_web или python_web вручную. Список нужен для автоопределения, а не для ограничения.

Cold start​

Контейнер поднимается по первому запросу, обслуживает трафик и засыпает при простое. Это значит:

  • Разбуженное из «тёплого» состояния приложение отвечает за ~0.2 с, полностью холодный старт — 4–12 с в зависимости от стека (Python быстрее, Streamlit медленнее). Это медианы реальных замеров; таблица по типам приложений и все состояния — в Жизненном цикле.
  • Приложения с регулярным трафиком платформа прогревает автоматически.
  • В простое проект ничего не стоит по compute — за это serverless и любят.

Выделенный keep-warm (гарантированно без холодных стартов) — платная настройка в планах.

Stateless-инвариант​

Файловая система контейнера эфемерна — это важное ограничение, которое легко проглядеть. Прочтите Stateless-инвариант прежде чем мигрировать существующее SSR-приложение, использующее SQLite, файловые сессии или локальный кеш.