Разделы документации
Порт, протокол и проверка готовности
Порт приложения, HTTP/1.1 или HTTP/2, путь проверки готовности и таймаут запроса.
Веб-приложение слушает один порт, который ты называешь в настройках, а платформа передаёт его приложению в переменной PORT. Рядом три настройки: протокол, путь проверки готовности и время на запрос. Все четыре запоминает версия, поэтому правка доезжает со следующим деплоем.
| Настройка | Поле API | По умолчанию | Допустимо |
|---|---|---|---|
| Порт | port |
нет, ты называешь его сам | от 1 до 65535, кроме 8012, 8013, 8022, 9090, 9091 |
| Протокол | protocol |
http1 |
http1 или h2c |
| Проверка готовности | health_check_path |
пусто: платформа проверяет только, что порт слушают | абсолютный путь до 255 символов |
| Время на запрос | request_timeout_seconds |
300 секунд | от 1 до 600 секунд |
Порт называешь ты, читает его приложение из PORT
Порт обязателен при создании веб-приложения. По API у поля port нет умолчания. В мастере создания в панели поле уже заполнено числом 3000, поменяй его на порт своего приложения.
Платформа кладёт этот номер в переменную окружения PORT. Читай её, а не вшивай число в код:
const port = process.env.PORT
app.listen(port)
Задать свою переменную PORT нельзя. Ответ 422 объясняет: имя занято платформой, она подставляет переменную сама, и твоё значение потерялось бы. Остальные переменные описаны в разделе Переменные и секреты.
Снаружи адрес приложения отвечает по HTTPS на порту 443 с сертификатом платформы. До приложения запрос доходит на твой порт без шифрования, поэтому TLS в приложении настраивать не нужно.
Пять портов платформа занимает рядом с приложением: 8012, 8013, 8022, 9090 и 9091. Заказ с таким портом отвечает 422 на поле port: «Порты 8012, 8013, 8022, 9090, 9091 платформа занимает рядом с приложением - возьми для него любой другой.» Соседние номера свободны, это список, а не диапазон.
Если приложение из образа или со своим Dockerfile, порт всё равно берётся из настройки, а не из строки EXPOSE. Подробности - в разделе Настройки сборки и свой Dockerfile.
Протокол: HTTP/1.1 или HTTP/2
Протокол описывает соединение от платформы до приложения. Снаружи адрес в любом случае остаётся HTTPS.
| Значение | Что это | Когда нужно |
|---|---|---|
http1 |
HTTP/1.1 | сайт, API, бот: так работает почти любое приложение |
h2c |
HTTP/2 без TLS | gRPC и всё, что рассчитывает на мультиплексирование |
Для gRPC выбери h2c. При http1 платформа сворачивает соединение до HTTP/1.1, и gRPC-клиент получает отказ, который похож на сбой сети, а не на несовпадение протокола. Выбирай h2c, только если приложение само принимает HTTP/2 без TLS.
Проверка готовности решает, когда версия получает трафик
Версия принимает запросы после того, как платформа убедилась, что приложение готово. Как она в этом убеждается, зависит от поля health_check_path:
- Путь не задан. Платформа проверяет, что порт слушают. Это становится правдой раньше, чем приложение может отвечать: пока оно прогревает кэш или применяет миграции, порт уже открыт.
- Путь задан, например
/healthz. Платформа делаетGETпо этому пути на порту приложения и пускает трафик на версию, когда приходит успешный ответ с кодом 2xx. Порт в пути не указывается.
Задай путь, если приложению нужно время на старт. Пусть он отвечает успехом, только когда приложение действительно может обслуживать запросы.
Путь начинается с /, не длиннее 255 символов, без пробелов и знака #. Строка запроса допустима: /health?full=0. Путь неверной формы отвечает 422.
Убрать проверку можно в любой момент. В панели очисти поле «Проверка готовности», по API пришли "health_check_path": null. Это единственное поле приложения, которое сбрасывается на null: пропущенное поле остаётся как было.
Проверка отвечает на вопрос «можно ли пускать трафик», а не «живо ли приложение». Приложение, которое зависло уже после запуска, платформа сама не перезапускает: такой проверки у неё нет.
Если путь отвечает ошибкой, не отвечает совсем или закрыт логином, версия не становится готовой. Деплой закончится причиной port_unreachable с тем же текстом про порт, что и при неверном порте: платформа не отличает молчащий порт от пути, который не возвращает успех. Работающая версия при этом отвечает как отвечала.
Время на запрос
Поле request_timeout_seconds задаёт, сколько платформа ждёт ответа на запрос. Дольше этого времени запрос обрывается. По умолчанию 300 секунд, пять минут, меньше одной секунды нельзя, больше 600 секунд тоже. Потолок установлен платформой, поднять его настройкой нельзя, а значение за пределами отвечает 422.
Настройки действуют со следующей версией
Версия снимает порт, протокол, путь проверки и время на запрос в момент заказа. Правка настроек ничего не деплоит и работающую версию не трогает. Новые значения заработают, когда закажешь версию, запушишь в ветку с включённым автодеплоем или отметишь «Задеплоить после сохранения».
В панели настройки лежат на странице приложения, на вкладке «Настройки»:
- «Имя и порт» - поле «Порт приложения»
- «Дополнительно» - блок «Как обращаться к приложению» с полями «Протокол до приложения», «Проверка готовности» и «Время на запрос»
После сохранения панель пишет «Настройки сохранены. Настройки снимет следующая версия». У приложения из архива флажка «Задеплоить после сохранения» нет: каждой версии нужен свой архив, и деплой начинается с загрузки.
По API настройки задаются в POST /api/v1/applications и меняются в PATCH /api/v1/applications/{id}. Правится ровно то, что прислано. Ответ GET /api/v1/applications/{id} отдаёт то, с чем уедет следующий деплой, а версия показывает значения, с которыми она заказана: поля protocol, health_check_path и request_timeout_seconds в ответе GET /api/v1/revisions/{id}. Пример:
{
"port": 8080,
"protocol": "h2c",
"health_check_path": "/healthz",
"request_timeout_seconds": 60
}
Откат возвращает прежнюю версию вместе с настройками, с которыми она работала, поэтому после отката приложение слушает тот порт, который слушала эта версия. Как работает откат, описано в разделе Версии и откат.
Три причины, по которым версия не поднялась
После сборки платформа запускает приложение и ждёт, пока оно станет готовым. Если версия не поднимается, платформа различает три исхода и каждый называет своей фразой. Фраза показана в панели под заголовком «Версия vN не доехала», а по API лежит в failure_reason версии и операции деплоя.
| Причина | Что видно | Когда приходит |
|---|---|---|
container_exited |
«Контейнер приложения завершился с кодом 1. Причину ищи в логе приложения.» | на третьем перезапуске, около 70 секунд после старта |
out_of_memory |
«Приложению не хватило памяти, и его процесс был остановлен. Возьми размер побольше.» | так же, на третьем перезапуске |
port_unreachable |
«Приложение запустилось, но не отвечает на порту 3000. Проверь, на каком порту оно слушает, и посмотри лог.» | через пять минут после старта |
Процесс, который завершается, платформа не судит с первого раза. Она ждёт три перезапуска подряд, пауза между ними растёт: 10, 20, 40 секунд. Поэтому приговор приходит около семидесятой секунды, а не на пятой минуте. Приложение, которое падает раз-другой, пока не поднимется база или другая зависимость, а потом работает, до конца деплоя доезжает.
Код выхода стоит в самой фразе. Его смысл знает только приложение, поэтому причину ищи в Логах приложения: там последние слова процесса. При out_of_memory размер увеличивается в разделе Размеры приложения.
Молчащий порт платформа отличает от медленного старта только по сроку: снаружи они выглядят одинаково. Поэтому на запуск версии отведено пять минут, и приговор о порте приходит ровно по их истечении. Версия, которой для старта нужно больше пяти минут, получает ту же причину. В фразе стоит номер порта из настроек: сверь его с тем, что слушает код.
Отказы запуска, которые не попали в эти три исхода, например образ, который не скачивается, закрываются общей причиной revision_not_ready со словами «Приложение не запустилось на выкаченной версии». Полный список причин отказа и что делать при каждой - в разделе Версии и откат.
Во всех трёх случаях работающая версия продолжает отвечать, если она была. Если версия первая, приложение остаётся в состоянии «Ошибка».
Типичные ошибки с портом
- Порт в коде не совпадает с настройкой. Приложение слушает 3000, а в настройках стоит 8080. Деплой закончится причиной
port_unreachableчерез пять минут. ПрочитайPORTв коде или поставь в настройках порт из кода и закажи новую версию. - Порт вшит в код. Число работает, пока настройка с ним совпадает, и ломается при первой смене порта. Читай переменную
PORT. - Порт указан только в
EXPOSE. Платформа эту строку не читает. Задай порт в настройках приложения. - Порт занят платформой. Один из
8012,8013,8022,9090,9091отвечает422ещё до деплоя. Возьми другой. - Новый порт не применился. Правка настроек не меняет работающую версию. Закажи версию, и она снимет настройки заново.
- Путь проверки отвечает ошибкой. Путь, которого нет в приложении, или путь за логином не отдаёт успех, и версия остаётся неготовой. Проверь путь запросом
GETбез авторизации. - gRPC не отвечает при
http1. Смени протокол наh2cи закажи версию.
У воркера порта и проверки нет
У воркера нет HTTP-сервиса, поэтому нет порта, протокола, пути проверки и времени на запрос. В панели этих полей у воркера нет. API отвечает 422 на каждое из четырёх полей: port, protocol, health_check_path и request_timeout_seconds. Чем воркер отличается от веб-приложения, описано в разделе Веб-приложения и воркеры.
Что дальше
- Версии и откат - полный список причин отказа и что делать при каждой
- Логи приложения - последние слова процесса, который не поднялся
- Настройки сборки и свой Dockerfile - как порт связан с Dockerfile
- Переменные и секреты - переменные работающего приложения
- Размеры приложения - что делать, когда не хватает памяти
- Веб-приложения и воркеры - у кого есть порт, а у кого нет
Страница в markdown, так её читает агент: /docs/apps/runtime.md