Деплой в продакшен

Деплой: NODE_ENV=production, менеджер процессов, graceful shutdown и обратный прокси перед приложением.
«Продакшен прощает мало. Приложение должно переживать перезапуски, падения и нагрузку без потери запросов.»

Финальный шаг — вывести приложение в интернет так, чтобы оно работало надёжно. Это не про "запустить node index.js на сервере": нужен менеджер процессов, корректное завершение, прокси и продакшен-настройки. В этом уроке соберём чек-лист готовности к проду.

Менеджер процессов

Просто node index.js на сервере умрёт при первой же ошибке и не поднимется. Менеджер процессов (PM2 или systemd) перезапускает упавшее приложение, запускает его в несколько процессов по числу ядер и пишет логи:

npm install -g pm2
# режим кластера: по процессу на ядро CPU
pm2 start index.js -i max --name my-api
pm2 save        # запомнить список процессов
pm2 startup     # автозапуск после перезагрузки сервера

Кластерный режим позволяет одному приложению использовать все ядра — каждое соединение уходит свободному процессу.

Graceful shutdown

При деплое или перезапуске нельзя обрывать запросы на полпути. Корректное завершение: перестать принимать новые соединения, дать текущим завершиться, закрыть базу — и только потом выйти:

const server = app.listen(PORT);

function shutdown() {
  console.log('Завершаюсь аккуратно...');
  server.close(() => {       // дослуживаем текущие запросы
    db.disconnect();         // закрываем соединение с базой
    process.exit(0);
  });
}

process.on('SIGTERM', shutdown);  // сигнал от системы/PM2
process.on('SIGINT', shutdown);   // Ctrl+C

Обратный прокси

Перед Node-приложением обычно ставят nginx или caddy. Прокси раздаёт HTTPS, отдаёт статику, балансирует нагрузку и прячет приложение от прямого доступа:

Интернет
   |  HTTPS
   v
[ nginx (обратный прокси) ]  -- TLS, статика, балансировка
   |  HTTP localhost:3000
   v
[ PM2 ] -> [ Node #1 ] [ Node #2 ] ... -- по ядру на процесс
   |
   v
[ база данных ]

Чек-лист готовности в браузере

Соберём проверку готовности к проду как набор условий — наглядно, чего нельзя забыть перед выкаткой:

function readinessCheck(env) {
  const checks = {
    'NODE_ENV=production': env.NODE_ENV === 'production',
    'есть JWT_SECRET':      Boolean(env.JWT_SECRET),
    'секрет длиннее 32':    (env.JWT_SECRET || '').length >= 32,
    'есть DATABASE_URL':    Boolean(env.DATABASE_URL)
  };
  const failed = Object.keys(checks).filter(k => !checks[k]);
  return failed.length ? 'НЕ ГОТОВО: ' + failed.join(', ') : 'Готово к проду';
}

console.log(readinessCheck({ NODE_ENV: 'development' }));
console.log(readinessCheck({
  NODE_ENV: 'production',
  JWT_SECRET: 'a'.repeat(40),
  DATABASE_URL: 'postgres://...'
}));

Как работает под капотом

Когда система или PM2 хотят остановить приложение, они шлют процессу сигнал SIGTERM. По умолчанию Node немедленно завершается, обрывая запросы. Подписавшись на сигнал, ты перехватываешь его и вызываешь server.close() — он перестаёт принимать новые соединения, но ждёт завершения текущих. PM2 в режиме reload поднимает новые процессы, ждёт их готовности и только потом гасит старые, обеспечивая нулевой простой.

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

  • Запуск через голый node. Упавшее приложение не поднимется само — нужен менеджер процессов.
  • Игнорировать SIGTERM. Без graceful shutdown деплой обрывает запросы пользователей.
  • Отдавать Node наружу напрямую. HTTPS, статику и балансировку лучше доверить прокси.

Best practices

  • Запускай через PM2/systemd в кластерном режиме с автозапуском.
  • Реализуй graceful shutdown по SIGTERM и SIGINT.
  • Ставь nginx/caddy перед приложением для HTTPS и статики; используй reload для деплоя без простоя.

Итоги

Прод — это менеджер процессов, корректное завершение, обратный прокси и продакшен-настройки. Собрав этот чек-лист, ты выкатываешь Express-приложение надёжно. Поздравляю: ты прошёл путь от голого http-сервера до защищённого, отказоустойчивого REST API в проде. Дальше — практика на собственных проектах.

Логи, метрики и здоровье

Выкатить приложение мало — за ним нужно наблюдать. В проде логи пишут в структурированном виде (JSON), чтобы их можно было искать и агрегировать, а не просто console.log в никуда. Отдельный маршрут /health, отвечающий, что сервис жив и база доступна, позволяет балансировщику и системе мониторинга автоматически замечать проблемы и убирать больной экземпляр из ротации. Метрики (время ответа, частота ошибок, нагрузка) собирают через APM-инструменты, чтобы видеть деградацию до того, как пожалуются пользователи. Эта наблюдаемость — не опциональное украшение: без неё ты узнаёшь о падении прода от клиентов, а не от приборов, и теряешь главное преимущество — время на реакцию.

Проверьте себя
1. Зачем нужен менеджер процессов вроде PM2?
AЧтобы писать меньше кода
BЧтобы перезапускать упавшее приложение и использовать все ядра CPU
CЧтобы заменить базу данных
DЧтобы шифровать трафик
2. Что делает graceful shutdown по сигналу SIGTERM?
AМгновенно убивает процесс
BПерестаёт принимать новые запросы, даёт текущим завершиться и закрывает ресурсы
CПерезагружает сервер
DОчищает базу данных