27. PM2 и деплой

PM2 — production process manager для Node.js. Следит за процессом, перезапускает при сбоях, кластеризация, логи.
Установка и запуск
Заголовок раздела «Установка и запуск»npm install -g pm2
# Запуск приложенияpm2 start src/index.js --name "my-api"
# С параметрамиpm2 start src/index.js \ --name "my-api" \ --instances 4 \ # 4 процесса (кластер) --max-memory-restart 500M # перезапуск при 500 МБ
# Из package.jsonpm2 start npm --name "my-api" -- startОсновные команды
Заголовок раздела «Основные команды»# Управлениеpm2 start app # запуститьpm2 stop app # остановитьpm2 restart app # перезапуститьpm2 reload app # zero-downtime перезапускpm2 delete app # удалить из PM2pm2 delete all # удалить все процессы
# Мониторингpm2 list # список процессовpm2 status # статус (синоним list)pm2 monit # интерактивный мониторингpm2 show app # детальная информация
# Логиpm2 logs # логи всех процессовpm2 logs app # логи конкретногоpm2 logs --lines 100 # последние 100 строкpm2 flush # очистить логи
# Системныеpm2 save # сохранить текущий списокpm2 startup # автозапуск при перезагрузкеpm2 unstartup # отключить автозапускecosystem.config.js — конфигурация
Заголовок раздела «ecosystem.config.js — конфигурация»module.exports = { apps: [ { name: 'my-api', script: './src/index.js',
// Кластер instances: 'max', // число ядер CPU exec_mode: 'cluster', // cluster mode
// Переменные окружения env: { NODE_ENV: 'development', PORT: 3000, }, env_production: { NODE_ENV: 'production', PORT: 3000, },
// Мониторинг и перезапуск max_memory_restart: '500M', min_uptime: '10s', // min время работы (иначе — ошибка старта) max_restarts: 10, // макс. перезапусков подряд restart_delay: 4000, // задержка между перезапусками
// Наблюдение за файлами (для dev) watch: false, ignore_watch: ['node_modules', 'logs', '.git'],
// Логи log_file: './logs/combined.log', out_file: './logs/out.log', error_file: './logs/error.log', log_date_format: 'YYYY-MM-DD HH:mm:ss Z', merge_logs: true, // один файл для кластера
// Graceful shutdown kill_timeout: 5000, // время на завершение (мс) listen_timeout: 10000, // время на запуск
// Cron перезапуск (каждый день в 3:00) cron_restart: '0 3 * * *', }, ],};# Запуск из конфигаpm2 start ecosystem.config.jspm2 start ecosystem.config.js --env productionpm2 reload ecosystem.config.js --env production # zero-downtimeCluster Mode — кластеризация
Заголовок раздела «Cluster Mode — кластеризация»// PM2 в cluster mode запускает несколько копий// Каждая на своём ядре CPU → параллельная обработка
{ instances: 'max', // = количество ядер CPU exec_mode: 'cluster', // кластер mode}
// Или через CLIpm2 start app.js -i max // -i = instancespm2 start app.js -i 4 // 4 процесса
// Масштабирование на летуpm2 scale app +2 // добавить 2 процессаpm2 scale app 4 // установить 4 процессаpm2 scale app -1 // убрать 1 процесс// Внимание: в кластере каждый процесс отдельный!// Общий state (in-memory) НЕ шарится!
// ❌ Не работает в кластереlet users = []; // у каждого процесса свой массивlet requestCount = 0; // у каждого свой счётчик
// ✅ Используй Redis для общего состоянияconst redis = require('ioredis');const client = new Redis(process.env.REDIS_URL);Деплой на VPS
Заголовок раздела «Деплой на VPS»# 1. Подготовка сервераssh user@serversudo apt update && sudo apt upgrade -ycurl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -sudo apt install -y nodejs nginxsudo npm install -g pm2
# 2. Клонируем проектgit clone https://github.com/user/my-api.git /var/www/my-apicd /var/www/my-apinpm ci --production
# 3. Настраиваем .envcp .env.example .envnano .env # заполняем реальные значения
# 4. Запускаем через PM2pm2 start ecosystem.config.js --env productionpm2 save # сохранить для автозапускаpm2 startup # автозапуск при перезагрузке ОСNginx как reverse proxy
Заголовок раздела «Nginx как reverse proxy»server { listen 80; server_name api.example.com;
# Перенаправление на HTTPS return 301 https://$host$request_uri;}
server { listen 443 ssl http2; server_name api.example.com;
# SSL сертификат (Let's Encrypt) ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
# Безопасность ssl_protocols TLSv1.2 TLSv1.3;
# Лимит размера тела запроса client_max_body_size 10M;
# Proxy к Node.js location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; }}# Включаем сайтsudo ln -s /etc/nginx/sites-available/my-api /etc/nginx/sites-enabled/sudo nginx -t # проверка конфигаsudo systemctl reload nginx
# SSL через Certbotsudo apt install certbot python3-certbot-nginxsudo certbot --nginx -d api.example.comCI/CD: автодеплой через GitHub Actions
Заголовок раздела «CI/CD: автодеплой через GitHub Actions»name: Deploy
on: push: branches: [main]
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Deploy to server uses: appleboy/ssh-action@v1 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USER }} key: ${{ secrets.SSH_KEY }} script: | cd /var/www/my-api git pull origin main npm ci --production npx prisma migrate deploy pm2 reload ecosystem.config.js --env productionПрактика
Заголовок раздела «Практика»- Установи PM2 и запусти приложение с
--name my-api - Создай
ecosystem.config.jsс настройками кластера, логов и перезапуска - Настрой автозапуск через
pm2 startupиpm2 save - Настрой Nginx как reverse proxy с SSL
- Реализуй автодеплой через GitHub Actions (ssh + pm2 reload)