Table of Contents
Введение
Node.js — среда исполнения JavaScript с открытым исходным кодом, предназначенная для построения серверных и сетевых приложений. Данная платформа работает в операционных системах Linux, macOS, FreeBSD и Windows. Хотя вы можете запускать приложения Node.js через командную строку, этот обучающий модуль посвящен их запуску в качестве службы. Это означает, что они будут перезапускаться при перезагрузке системы или неисправности, и что их можно безопасно использовать в производственной среде.
В этом обучающем модуле вы научитесь создавать готовую производственную среду Node.js на одном сервере Ubuntu 18.04. Этот сервер будет выполнять приложение Node.js под управлением PM2 и предоставлять пользователям безопасный доступ к приложению через обратный прокси-сервер Nginx. Сервер Nginx обеспечивает поддержку HTTPS с использованием бесплатного сертификата от Let's Encrypt.
Предварительные требования
Этот обучающий модуль предполагает, что у вас имеется следующее:
- Сервер Ubuntu 18.04, настроенный в соответствии с указаниями обучающего модуля Начальная настройка сервера Ubuntu 18.04. В системе должен быть задан пользователь без привилегий root с привилегиями sudo, а также должен быть включен брандмауэр.
- Доменное имя, указывающее на публичный IP-адрес вашего сервера. В этом обучающем модуле мы будем использовать доменное имя example.com.
- Веб-сервер Nginx, установленный в соответствии с указаниями обучающего модуля Установка Nginx в Ubuntu 18.04.
- Конфигурация Nginx с SSL с использованием сертификатом Let's Encrypt. Защита веб-сервера Nginx сертификатом Let's Encrypt в Ubuntu 18.04 поможет вам выполнить необходимые настройки.
Если предварительные требования выполнены, у вас должен быть сервер, обслуживающий используемую по умолчанию страницу назначения вашего домена по адресу https://<^>example.com<^>/.
Шаг 1 — Установка Node.js
Для начала мы установим самый быстрый выпуск LTS Node.js, используя архивы пакетов NodeSource.
Вначале мы установим NodeSource PPA, чтобы получить доступ к его содержимому. Перейдите в каталог home и используйте curl для получения скрипта установки архивов Node.js 8.x:
cd ~
curl -sL https://deb.nodesource.com/setup_8.x -o nodesource_setup.sh
Вы можете просмотреть содержимое скрипта с помощью nano или предпочитаемого текстового редактора:
nano nodesource_setup.sh
Завершив проверку скрипта, запустите его от имени пользователя sudo:
sudo bash nodesource_setup.sh
Архив PPA будет добавлен в вашу конфигурацию и кэш локальных пакетов автоматически обновится. После запуска скрипта установки Nodesource вы можете установить пакет Node.js:
sudo apt install nodejs
Чтобы проверить номер версии Node.js, установленной на начальном шаге, введите:
nodejs -v
[secondary_label Output]
v8.11.3
Примечание. При установке из NodeSource PPA исполняемый файл Node.js имеет имя nodejs, а не node.
Пакет nodejs содержит двоичный файл nodejs, а также диспетчер пакетов npm для модулей Node, так что отдельно устанавливать npm не нужно.
npm использует файл конфигурации в домашнем каталоге, чтобы отслеживать обновления. Он создается при первом запуске npm. Выполните следующую команду, чтобы проверить установку npm и создать файл конфигурации:
npm -v
[secondary_label Output]
5.6.0
Для работы некоторых пакетов npm (например, требующих компиляцию кода из источника) потребуется установить пакет build-essential:
sudo apt install build-essential
Теперь у вас есть необходимые инструменты для работы с пакетами npm, которые требуют компиляции кода из источника.
Установив исполняемый модуль Node.js, мы можем перейти к написанию приложения Node.js.
Шаг 2 — Создание приложения Node.js
Напишем приложение *Hello World*, возвращающее «Hello World» в ответ на любые запросы HTTP. Этот образец приложения поможет вам выполнить настройку Node.js. Вы можете заменить его собственным приложением, но при этом обязательно измените приложение для прослушивания подходящих IP-адресов и портов.
Вначале создадим образец приложения под именем hello.js:
cd ~
nano hello.js
Вставьте в файл следующий код:
[label ~/hello.js]
const http = require('http');
const hostname = 'localhost';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World!\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
Сохраните файл и выйдите из редактора.
Это приложение Node.js прослушивает заданный адрес (localhost) и порт (3000) и возвращает текст «Hello World!» с кодом успешного выполнения a 200 HTTP. Поскольку мы прослушиваем localhost, удаленные клиенты не смогут подключиться к нашему приложению.
Чтобы протестировать приложение, введите:
node hello.js
Результат будет выглядеть следующим образом:
[secondary_label Output]
Server running at http://localhost:3000/
Примечание. Такой способ запуска приложения Node.js блокирует дополнительные команды, пока приложение не будет закрыто нажатием CTRL+C.
Чтобы протестировать приложение, откройте на сервере другой сеанс терминала и подключитесь к localhost с помощью команды curl:
[environment second]
curl http://localhost:<^>3000<^>
Если вы увидите следующий результат, приложение работает нормально и прослушивает правильные адрес и порт:
[secondary_label Output]
[environment second]
Hello World!
Если вы не видите ожидаемого результата, убедитесь, что ваше приложение Node.js запущено и настроено для прослушивание правильных адреса и порта.
Убедившись, что приложение работает, остановите его (если еще не сделали этого) нажатием CTRL+C.
Шаг 3 — Установка PM2
Теперь установим диспетчер процессов PM2, предназначенный для приложений Node.js. PM2 позволяет преобразовывать приложения в демонов, чтобы они работали как службы в фоновом режиме.
Используйте npm для установки последней версии PM2 на своем сервере:
sudo npm install pm2@latest -g
Опция -g указывает npm выполнить глобальную установку модуля, чтобы он был доступен _в масштабе всей системы_.
Вначале используем команду pm2 для запуска вашего приложения hello.js в фоновом режиме:
pm2 start <^>hello.js<^>
Также она добавит ваше приложение в список процессов PM2, которы йвыводится при каждом запуске приложения:
[secondary_label Output]
[PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Starting /home/sammy/hello.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬───────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼───────┼──────────┤
│ <^>hello<^> │ 0 │ fork │ 1338 │ online │ 0 │ 0s │ 0% │ 23.0 MB │ sammy │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴───────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
Как видите, PM2 автоматически назначает App name (по имени файла, без расширения .js и идентификатор PM2 id. PM2 также обслуживает и другие данные, в том числе PID процесса, данные о текущем состоянии и использовании памяти.
Приложения, запускаемые через PM2, автоматически перезапускаются в случае сбоя или прекращения работы приложения, но мы можем выполнить дополнительный шаг, чтобы запускать приложение при запуске системы с помощью субкоманды startup. Эта субкоманда генерирует и настраивает скрипт запуска PM2 и управляемых им процессов при загрузке сервера:
pm2 startup systemd
Последняя строка результатов содержит команду, которую нужно запустить с привилегиями суперпользователя для настройки запуска PM2 при загрузке:
[secondary_label Output]
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
<^>sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy<^>
Запустите команду из результатов, указав свое имя пользователя вместо <^>sammy<^>:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u <^>sammy<^> --hp /home/<^>sammy<^>
Дополнительно мы можем сохранить список процессов PM2 и соответствующие среды:
pm2 save
Теперь вы создали *блок* systemd, который запускает pm2 для вашего пользователя при загрузке. Этот экземпляр pm2 запускает hello.js.
Запустите службу с помощью команды systemctl:
sudo systemctl start pm2-<^>sammy<^>
Проверьте состояние блока systemd:
systemctl status pm2-<^>sammy<^>
Подробный обзор systemd можно найти в документе «Основы работы с Systemd: работа со службами, блоками и журналом».
В дополнение к уже описанным субкомандам PM2 предоставляет много субкоманд, позволяющих управлять информацией о ваших приложениях и искать такую информацию.
Остановите приложение с помощью этой команды (укажите имя приложения PM2 или id):
pm2 stop <^>app_name_or_id<^>
Перезапустите приложение:
pm2 restart <^>app_name_or_id<^>
Выведем список приложений, управление которыми осуществляет PM2:
pm2 list
Получим информацию об определенном приложении по App name:
pm2 info <^>app_name<^>
Монитор процесса PM2 запускается с помощью субкоманды monit. При этом отображается состояние приложение, использование ресурсов ЦП и использование памяти:
pm2 monit
При запуске команды pm2 без аргументов отображается страница справки с примерами использования.
Теперь ваше приложение Node.js запущено и управляется PM2, и мы можем настроить обратный прокси-сервер.
Шаг 4 — Настройка Nginx в качестве обратного прокси-сервера
Ваше приложение запущено и прослушивает localhost, но вам нужно дать пользователям возможность доступа к нему. Для этой цели мы настроим веб-сервер Nginx в качестве обратного прокси-сервера.
В предварительных обучающих модулях вы настроили конфигурацию Nginx в файле /etc/nginx/sites-available/<^>example.com<^>. Откройте этот файл для редактирования:
sudo nano /etc/nginx/sites-available/<^>example.com<^>
В блоке server должен содержаться блок location /. Замените содержимое этого блока следующей конфигурацией. Если ваше приложение настроено для прослушивания другого порта, измените номер порта в выделенной части на подходящий:
[label /etc/nginx/sites-available/example.com]
server {
...
location / {
proxy_pass http://localhost:<^>3000<^>;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
...
}
Так сервер настраивается для ответа на запросы root. Если наш сервер доступен по адресу <^>example.com<^>, при попытке доступа к https://<^>example.com<^>/ через браузер будет отправлен запрос hello.js с прослушиванием порта 3000 хоста localhost.
Вы можете добавить в этот же серверный блок дополнительные блоки location, чтобы предоставить другим приложениям доступ к этому же серверу. Например, если вы используете другое приложение Node.js на порту 3001, вы сможете добавить следующий блок location, чтобы разрешить доступ к нему через https://<^>example.com<^>/<^>app2<^>:
[label /etc/nginx/sites-available/example.com — Optional]
server {
...
location /<^>app2<^> {
proxy_pass http://localhost:<^>3001<^>;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
...
}
Завершив добавление блоков location для ваших приложений, сохраните файл и закройте редактор.
Убедитесь в отсутствии ошибок синтаксиса с помощью следующей команды:
sudo nginx -t
Перезапустите Nginx:
sudo systemctl restart nginx
Если ваше приложение Node.js запущено и конфигурации вашего приложения и Nginx настроены правильно, вы должны иметь возможность доступа к вашему приложению через обратный прокси-сервер Nginx. Попробуйте открыть URL вашего сервера (публичный IP-адрес или доменное имя).
Заключение
Поздравляем! Теперь у вас есть приложение Node.js, работающее за обратным прокси-сервером Nginx на сервере Ubuntu 18.04. Настройка обратного прокси-сервера достаточно гибкая, чтобы предоставить вашим пользователям доступ к другим приложениям или статическому веб-контенту, который вы хотите опубликовать.