Hostim Docs

Деплой Node.js-приложения

Эта статья дополняет общие правила из «Что нужно, чтобы деплой прошёл» конкретикой для Node.js. Всё, что нужно, задаётся в одном файле — package.json: зависимости, команда запуска и версия Node.

Шаг 1. Зависимости и lock-файл

Nixpacks определяет Node.js по package.json в корне репозитория и устанавливает то, что перечислено в dependencies. Закоммитьте вместе с ним файл блокировки версий (package-lock.json, pnpm-lock.yaml или yarn.lock) — по нему выбирается пакетный менеджер и точные версии.

Пакет, установленный локально без сохранения в package.json (npm install <пакет> без записи в зависимости), на сборке будет отсутствовать. Устанавливайте с флагом сохранения: npm install <пакет> записывает зависимость по умолчанию, проверьте, что она попала в файл.

Шаг 2. Команда запуска — скрипт start

Nixpacks запускает приложение командой npm start, то есть берёт скрипт start из package.json. Задайте его явно:

{
  "scripts": {
    "start": "node index.js"
  }
}

Без скрипта start сборщик попытается угадать точку входа и может запустить не то. Не полагайтесь на угадывание.

Пример: Web-сервис (Express)

Web-сервис принимает HTTP-запросы и получает домен. Приложение обязано слушать порт из переменной PORT (см. общую статью).

package.json:

{
  "name": "my-app",
  "engines": { "node": "22" },
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^4.19.0"
  }
}

index.js:

const express = require("express");
const app = express();

app.get("/", (req, res) => res.json({ status: "ok" }));

const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`listening on ${port}`));

HTTP-сервер Node.js (и Express) по умолчанию слушает на 0.0.0.0, поэтому здесь достаточно указать правильный порт. Значение || 3000 — только для локального запуска; на платформе PORT придёт из окружения.

Пример: Worker-сервис (Telegram-бот)

Worker работает в фоне, не принимает HTTP и не имеет домена. Порт слушать не нужно. Токен читается из переменных окружения.

package.json:

{
  "name": "my-bot",
  "engines": { "node": "22" },
  "scripts": {
    "start": "node bot.js"
  },
  "dependencies": {
    "telegraf": "^4.16.0"
  }
}

bot.js:

const { Telegraf } = require("telegraf");

const bot = new Telegraf(process.env.BOT_TOKEN);
bot.start((ctx) => ctx.reply("Привет"));
bot.launch();

Значение BOT_TOKEN задаётся в переменных окружения сервиса — см. «Переменные окружения и секреты».

Версия Node.js

Укажите её в поле engines.node файла package.json (как в примерах выше) или в файле .nvmrc. Без указания берётся актуальная LTS-версия.

Проект на TypeScript

Если код на TypeScript, нужен шаг сборки перед запуском:

  • добавьте скрипт build (например, "build": "tsc") — Nixpacks выполнит его автоматически;
  • в start укажите запуск уже скомпилированного файла (например, "start": "node dist/index.js");
  • инструменты сборки (typescript и типы) держите в devDependencies — при сборке они устанавливаются.

Частые ошибки

СимптомПричинаРешение
Cannot find module при запускеЗависимость не записана в package.jsonДобавьте её в dependencies, закоммитьте lock-файл
Сборка прошла, но контейнер сразу останавливаетсяНет скрипта start или неверный путь к файлуЗадайте start, проверьте путь
Домен отдаёт 502Приложение слушает фиксированный порт вместо PORTИспользуйте process.env.PORT
Сборка TypeScript падает: не найден tscЗадана переменная NODE_ENV=productiondevDependencies не ставятсяНе задавайте NODE_ENV=production для сборки или перенесите инструменты в dependencies
Бот не отвечает, ошибка про токенТокен захардкожен или не заданЗадайте BOT_TOKEN в переменных окружения

Дальше