Когда нужен 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_next | Next.js с SSR или API-роутами. |
node_web | Любой Node-сервер, слушающий HTTP: Express, Fastify, NestJS, Koa, Hono и другие. |
python_web | Любое WSGI/ASGI-приложение: Django, FastAPI, Flask, Starlette, Litestar и другие. |
streamlit | Streamlit-приложение (нужен app.py). |
gradio | Gradio-приложение (нужен 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; число воркеров зависит от памяти инстанса |
| Django | uvicorn <проект>.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, файловые сессии или локальный кеш.