Головна / Статті / Практична схема для випуску додатків Node.js у продакшн

Практична схема для випуску додатків Node.js у продакшн

Ознайомтесь із повним переліком перевірок для створення додатків на Node.js, який охоплює сервери, конфіденційні дані, керування процесами, HTTPS, CI/CD, логування та резервне копіювання.

2042 слів

Запуск додатку Node.js на власному комп’ютері — це найпростіша частина.

npm run dev

Ваш API відповідає. Ваша база даних підключена. Усе, здається, працює без проблем.

Потім хтось запитує:

"Гаразд, як нам розгорнути це в продакшені?"

Саме тоді стає зрозуміло, що створення API — це лише половина роботи.

Перехід у продакшен породжує цілу низку нових запитань:

  • Де насправді буде працювати додаток?
  • Що буде забезпечувати його роботу у разі збою?
  • Як вхідний трафік доходить до процесу Node.js?
  • Де слід зберігати змінні середовища?
  • Як налаштувати HTTPS?
  • Як випускати нові версії?
  • Як виявляти помилки, коли вони трапляються?
  • Що станеться, якщо сам сервер перезавантажиться?

Ось практична схема для розуміння налаштувань продакшн-середовища Node.js.

1. Зрозуміти архітектуру продакшну

Типове налаштування для продакшну виглядає приблизно так:

                    Internet
                       │
                       ▼
                  ┌─────────┐
                  │  Nginx  │
                  │  :80/443│
                  └────┬────┘
                       │
                       ▼
                ┌─────────────┐
                │   Node.js   │
                │ Application │
                └──────┬──────┘
                       │
              ┌────────┼────────┐
              ▼        ▼        ▼
          PostgreSQL  Redis   External APIs

Ключовий принцип полягає у тому, що кінцеві користувачі зазвичай не повинні під’єднуватися безпосередньо до чогось на кшталт:

localhost:3000

Натомість Nginx розташовується попереду, приймаючи публічні запити та передаючи їх вашому додатку Node.js.

2. Підготувати сервер

Ви можете орендувати VPS або віртуальну машину в хмарі у таких провайдерів, як AWS, GCP, Azure чи DigitalOcean.

Перш ніж робити щось інше, вам потрібно налаштувати саму машину.

У Ubuntu це зазвичай починається з:

sudo apt update
sudo apt upgrade -y

Після цього встановіть усі інструменти, необхідні для роботи вашого додатку.

Для самого Node.js зазвичай доцільно встановлювати його за допомогою менеджера версій, такого як nvm, щоб можна було точно контролювати, яка версія працює.

Перевірте встановлені версії за допомогою:

node -v
npm -v

Версія Node, яка працює в продакшені, має збігатися з тією, яку ви тестуєте локально.

Це може здатися дрібницею, але несумісні версії можуть спричинити складні для виявлення помилки після розгортання.

3. Не зберігайте конфіденційну інформацію у коді

Цю помилку легко припуститися, але її також легко уникнути.

Уникайте вбудовування облікових даних у код ось так:

const DATABASE_URL =
  "postgresql://user:password@database.com/mydb";

І ніколи не додавайте конфіденційну інформацію до історії Git.

Натомість визначайте їх як змінні середовища:

NODE_ENV=production
PORT=3000
DATABASE_URL=postgresql://...
REDIS_URL=redis://...
JWT_SECRET=...

Потім читайте їх у своєму коді за допомогою:

process.env.DATABASE_URL

Переконайтеся, що ваші файли .env виключені з контролю версій:

.env
.env.production

Одна викрита пароль до бази даних може завдати набагато більшої шкоди, ніж будь-яка помилка під час розгортання.

4. Створення додатку

Перш ніж запустити додаток, встановіть лише залежності для продакшну та виконайте крок компіляції, якщо це необхідно для вашої фреймворк-системи.

Наприклад, проект на TypeScript може виконуватися так:

npm ci
npm run build

А потім запустіть скомпільований результат за допомогою:

npm start

Конкретні команди будуть відрізнятися залежно від вашої технологічної стеку.

Важливим є такий принцип:

Трафік з продакшну має потрапляти до вашої версії додатку для продакшну, а не до сервера розробки.

Іншими словами, не залишайте випадково щось на кшталт:

npm run dev

яке працює як ваш основний процес.

5. Що відбувається, якщо Node.js зламається?

Припустимо, ви запускаєте свій додаток безпосередньо так:

node dist/server.js

У певний момент щось йде не так, і процес раптово зупиняється.

Ваш API тепер не працює, і немає способу його відновити.

Саме цю проблему вирішує менеджер процесів.

PM2 є широко поширеним вибором для цього.

Встановіть його глобально:

npm install -g pm2

Потім запустіть ваш додаток під наглядом PM2:

pm2 start dist/server.js --name my-api

Перевірте його статус:

pm2 status

Перегляньте журнали:

pm2 logs my-api

Або перезапустіть його за потреби:

pm2 restart my-api

Справа не лише у простоті використання. Суть у тому, що ваш процес тепер активно контролюється, замість того щоб працювати у вікні терміналу з надією, що ніщо його не зупинить.

6. Змусити додаток запуститися після перезавантаження сервера

Сервери іноді перезавантажуються, чи то навмисно, чи нещодухома.

Наприклад:

Server reboot
     ↓
Operating system starts
     ↓
Node.js application?

Ви не хочете щоразу вручну підключатися через SSH, коли це трапляється.

PM2 може створити скрипт запуску для вашої системи:

pm2 startup

Потім збережіть список поточно запущених процесів:

pm2 save

З цим рішенням ваше додатку може автоматично повернутися до роботи після перезавантаження.

7. Розмістити Nginx перед Node.js

Припустимо, ваш сервер Node.js працює на:

localhost:3000

Але ваші користувачі підключаються через:

https://api.example.com

Nginx може подолати цю проблему, виступаючи як зворотний проксі.

Спрощена конфігурація може виглядати так:

server {
    listen 80;server_name api.example.com;
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

З цим шлях запиту стає таким:

User
  ↓
https://api.example.com
  ↓
Nginx :80
  ↓
Node.js :3000

Таким чином, порт, на якому працює додаток Node.js, ніколи не потребує прямого доступу з інтернету.

8. Додати HTTPS

Робота вашого продакшн-API на звичайному

http://

Цього недостатньо. Його потрібно отримувати через

https://

Широко поширеним підходом є поєднання Let's Encrypt з Certbot.

Спочатку встановіть Certbot:

sudo apt install certbot python3-certbot-nginx

Потім зверніться та отримайте сертифікат для вашого домену:

sudo certbot --nginx -d api.example.com

Certbot бере на себе організацію сертифіката та налаштування HTTPS від вашого імені.

Після цього процес заявки виглядає так:

Client
   ↓
HTTPS
   ↓
Nginx
   ↓
Node.js
   ↓
Database / Redis

9. Не забувайте про брандмауер

Не кожен порт на вашому сервері має бути доступним ззовні.

Зазвичай ви хочете, щоб публіка могла доступатися до:

80   → HTTP
443  → HTTPS

разом із доступом через SSH на:

22

Порти, які використовуються PostgreSQL чи Redis, зазвичай не повинні бути відкритими для Інтернету, якщо у вас немає конкретної причини та суворих механізмів контролю доступу.

Точні правила будуть варіюватися залежно від вашої конфігурації, але основне правило залишається незмінним:

Відкривайте доступ лише до того, що дійсно потребує цього.

10. Ручне розгортання працює, поки це можливо

На початковому етапі розгортання може полягати просто у:

git pull
npm install
npm run build
pm2 restart my-api

Це цілком прийнятно для невеликого проекту.

Але рано чи пізно ви помітите, що постійно повторюєте одну й ту саму послідовність дій:

Developer pushes code
       ↓
SSH into server
       ↓
git pull
       ↓
install dependencies
       ↓
build
       ↓
restart

У такому випадку доцільно автоматизувати процес.

11. CI/CD змінює процес роботи

Використовуючи інструменти на кшталт GitHub Actions, процес може змінитися на:

Developer
    ↓
git push
    ↓
GitHub
    ↓
CI/CD Pipeline
    ↓
Build + Test
    ↓
Deploy
    ↓
Production

Мінімальна визначення процесу роботи може виглядати так:

name: Deploy
on:
  push:
    branches:
      - mainjobs:
  deploy:
    runs-on: ubuntu-latest    steps:
      - uses: actions/checkout@v4      - name: Install dependencies
        run: npm ci      - name: Build
        run: npm run build      - name: Test
        run: npm test

Конкретні кроки розгортання залежатимуть від вашої інфраструктури.

Важливішим є основний принцип:

Не автоматизуйте процес розгортання, якого ви ще не розумієте.

Спочатку навчіться робити це вручну.

Лише тоді перетворюйте повторювані кроки на автоматизацію.

12. Логування — це не опція

Додаток може здаватися працездатним, навіть коли справжні користувачі стикаються з помилками.

Логи — це те, що допомагає це з’ясувати.

Принаймні вам потрібні відповіді на такі запитання:

When did the error happen?
Which endpoint failed?
What status code was returned?
What was the error?
How long did the request take?

Простий приклад:

console.error({
  message: error.message,
  endpoint: req.originalUrl,
  method: req.method,
  timestamp: new Date().toISOString()
});

Для будь-чого, що працює у великих масштабах, структуровані логи у поєднанні з централізованим збиранням логів допоможуть значно більше, ніж розкидані по коду виклики console.log().

13. Контролюйте більше, ніж лише помилки

Відсутність винятків не означає, що ваша система у гарному стані.

Вам також потрібен огляд таких аспектів, як:

CPU
Memory
Disk
Request latency
Error rate
Database performance
Redis health
Traffic

Наприклад:

Requests       → 1,500/min
Average latency → 180ms
Error rate      → 0.4%
CPU             → 42%
Memory          → 61%

Подібні показники дають набагато повнішу картину того, як насправді працює ваша система.

14. Резервні копії важливіші за розгортання

Ось ситуація, про яку більшість розробників воліли б не думати:

Production database
       ↓
Something goes wrong
       ↓
Data disappears

Ви завжди можете знову розгорнути код свого додатку.

Однак ваша база даних може містити дані, які просто неможливо відтворити після їх втрати.

Саме тому резервні копії також не є опційними.

Вам потрібен план резервного копіювання для всього важливого у продакшені, і не менш важливо — знати, як насправді відновити дані з цих резервних копій.

Резервна копія, яку ви ніколи не пробували відновлювати, — це та, якій не варто довіряти.

15. Розгортання без перерв є окремою проблемою

У певний момент тимчасове відключення додатку для розгортання перестає бути прийнятним.

Розгляньте таку ситуацію:

Old version running
       ↓
New version deployed
       ↓
Traffic gradually moves
       ↓
Old version removed

Залежно від того, як налаштована ваша інфраструктура, ви можете скористатися:

  • Запуском кількох копій процесу Node.js одночасно
  • Вбудованим режимом кластеру PM2
  • Балансувальником навантаження, який розподіляє трафік між інстанціями
  • Поступовим впровадженням оновлень, по одному серверу за раз, замість того щоб робити це одночасно
  • Перекиданням трафіку між старим та новим середовищем (у стилі blue-green)
  • Упакуванням додатку у контейнери
  • Оркестрацією всього за допомогою Kubernetes

Проте наявність API на Node.js не означає автоматично потреби у Kubernetes.

Спочатку залишайте все простим, а розширюйте архітектуру лише тоді, коли це необхідно через ваші реальні вимоги.

16. Мій чек-лист для продакшну

Перш ніж вважати додаток на Node.js готовим до продакшну, варто перевірити наступне:

[ ] Production environment configured
[ ] Secrets stored securely
[ ] Database connection configured
[ ] Redis configured if required
[ ] Production build tested
[ ] Process manager configured
[ ] Application restart tested
[ ] Nginx configured
[ ] HTTPS configured
[ ] Firewall configured
[ ] Logs available
[ ] Error monitoring configured
[ ] Database backups configured
[ ] Backup restoration tested
[ ] Deployment process documented
[ ] CI/CD configured if needed
[ ] Health check endpoint available

17. Архітектура, яку я маю на увазі

Базове середовище для роботи системи Node.js зазвичай виглядає приблизно так:

                    ┌─────────────┐
                    │   Internet  │
                    └──────┬──────┘
                           │
                           ▼
                    ┌─────────────┐
                    │    Nginx    │
                    │  SSL / Proxy│
                    └──────┬──────┘
                           │
                 ┌─────────┴─────────┐
                 ▼                   ▼
          ┌────────────┐      ┌────────────┐
          │  Node.js   │      │  Node.js   │
          │ Instance 1 │      │ Instance 2 │
          └─────┬──────┘      └─────┬──────┘
                │                   │
                └─────────┬─────────┘
                          │
              ┌───────────┼───────────┐
              ▼           ▼           ▼
         PostgreSQL     Redis    External APIs

А навколо цього ядра зазвичай потрібно:

Monitoring
Logging
Backups
CI/CD
Security

Останні думки

Випуск додатку Node.js у продакшн — це ніколи не просто:

npm start

Справжня робота в продакшні означає планування всього того, що відбувається після запуску процесу.

Який у вас план, якщо все зламається несподівано?

Як поводиться система після перезавантаження сервера?

Яка буде реакція на раптовий сплеск вхідного трафіку?

Що відбувається, коли база даних стає недоступною?

Як ви відновлюєте ситуацію після випуску несправної версії?

Який протокол дій, якщо облікові дані випадково стануть доступними?

Ось ця прогалина між:

„Це працює на моєму комп’ютері.“

і

„Це надійно працює у продакшені.“

Вам не потрібна величезна інфраструктура з самого початку.

Почніть з малого.

Зрозумійте кожен елемент, який ви додаєте.

Автоматизуйте те, що повторюється.

Стежте за показниками, які справді мають значення.

Додавайте складність лише тоді, коли система справді цього вимагає.

Розгортання — це не кінцева мета розробки. Це той момент, коли по-справжньому починається експлуатація вашого програмного забезпечення.

Пов’язана література

  • Створення механізмів обробки помилок промислового рівня в додатках Node.js — Дізнайтеся, як класифікувати помилки в Node.js, розробляти власну ієрархію помилок, централізувати асинхронну обробку помилок та зберігати стек-трейси для підвищення стійкості додатків у промислових умовах.