Введение

Node.js — среда исполнения JavaScript с открытым исходным кодом, предназначенная для построения серверных и сетевых приложений. Данная платформа работает в операционных системах Linux, macOS, FreeBSD и Windows. Хотя вы можете запускать приложения Node.js через командную строку, этот обучающий модуль посвящен их запуску в качестве службы. Это означает, что они будут перезапускаться при перезагрузке системы или неисправности, и что их можно безопасно использовать в производственной среде.

В этом обучающем модуле вы научитесь создавать готовую производственную среду Node.js на одном сервере Ubuntu 20.04. Этот сервер будет выполнять приложение Node.js под управлением PM2 и предоставлять пользователям безопасный доступ к приложению через обратный прокси-сервер Nginx. Сервер Nginx обеспечивает поддержку HTTPS с использованием бесплатного сертификата от Let's Encrypt.

Предварительные требования

node.js illustration for: Предварительные требования

Этот обучающий модуль предполагает, что у вас имеется следующее:

  • Сервер Ubuntu 20.04, настроенный в соответствии с указаниями обучающего модуля Начальная настройка сервера Ubuntu 20.04. В системе должен быть задан пользователь без привилегий root с привилегиями sudo, а также должен быть включен брандмауэр.

Если предварительные требования выполнены, у вас должен быть сервер, обслуживающий используемую по умолчанию страницу назначения вашего домена по адресу https://<^>example.com<^>/.

Шаг 1 — Установка Node.js

Для начала мы установим самый быстрый выпуск LTS Node.js, используя архивы пакетов NodeSource.

Вначале мы установим NodeSource PPA, чтобы получить доступ к его содержимому. Убедитесь, что вы находитесь в домашнем каталоге, и используйте curl для получения скрипта установки для последней версии LTS Node.js из его архивов.

				
					
cd ~

curl -sL https://deb.nodesource.com/setup_&lt;^&gt;14&lt;^&gt;.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]

v&lt;^&gt;14.4.0&lt;^&gt;

				
			

Примечание. При установке из NodeSource PPA исполняемый файл Node.js имеет имя nodejs, а не node.

Пакет nodejs содержит двоичный файл nodejs, а также диспетчер пакетов npm для модулей Node, так что отдельно устанавливать npm не нужно.

npm использует файл конфигурации в домашнем каталоге, чтобы отслеживать обновления. Он создается при первом запуске npm. Выполните следующую команду, чтобы проверить установку npm и создать файл конфигурации:

				
					
npm -v

				
			
				
					
[secondary_label Output]

&lt;^&gt;6.14.5&lt;^&gt;

				
			

Для работы некоторых пакетов 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) =&gt; {

 res.statusCode = 200;

 res.setHeader('Content-Type', 'text/plain');

 res.end('Hello World!\n');

});



server.listen(port, hostname, () =&gt; {

 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:&lt;^&gt;3000&lt;^&gt;

				
			

Если вы увидите следующий результат, приложение работает нормально и прослушивает правильные адрес и порт:

				
					
[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 &lt;^&gt;hello.js&lt;^&gt;

				
			

Также она добавит ваше приложение в список процессов 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.

┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐

│ id │ name │ mode │ ↺ │ status │ cpu │ memory │

├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤

│ 0 │ hello │ fork │ 0 │ online │ 0% │ 25.2mb │

└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

				
			

Как указано выше, PM2 автоматически присваивает App name (основанное на имени файла, без расширения .js) и PM2 id. PM2 также обслуживает другие данные, такие как PID процесса, его текущее состояние и использование памяти.

Приложения, запускаемые через PM2, автоматически перезапускаются в случае сбоя или прекращения работы приложения, но мы можем выполнить дополнительный шаг, чтобы запускать приложение при запуске системы с помощью субкоманды startup. Эта субкоманда генерирует и настраивает скрипт запуска PM2 и управляемых им процессов при загрузке сервера:

				
					
pm2 startup systemd

				
			

Последняя строка результатов содержит команду, которую нужно запустить с привилегиями суперпользователя для настройки запуска PM2 при загрузке:

				
					
[secondary_label Output]

[PM2] Init System found: systemd

&lt;^&gt;sammy&lt;^&gt;

[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 &lt;^&gt;sammy&lt;^&gt; --hp /home/&lt;^&gt;sammy&lt;^&gt;

				
			

Запустите команду из результатов, указав свое имя пользователя вместо <^>sammy<^>:

				
					
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u &lt;^&gt;sammy&lt;^&gt; --hp /home/&lt;^&gt;sammy&lt;^&gt;

				
			

Дополнительно мы можем сохранить список процессов PM2 и соответствующие среды:

				
					
pm2 save

				
			

Теперь вы создали *блок* systemd, который запускает pm2 для вашего пользователя при загрузке. Этот экземпляр pm2 запускает hello.js.

Запустите службу с помощью команды systemctl:

				
					
sudo systemctl start pm2-&lt;^&gt;sammy&lt;^&gt;

				
			

Если на этом этапе вы увидите ошибку, вам может потребоваться перезагрузка, которую можно выполнить с помощью sudo reboot.

Проверьте состояние блока systemd:

				
					
systemctl status pm2-&lt;^&gt;sammy&lt;^&gt;

				
			

Подробный обзор блока systemd можно найти в разделе Основы работы с Systemd: работа со службами, блоками и журналом.

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

Остановите приложение с помощью этой команды (укажите имя приложения PM2 или id):

				
					
pm2 stop &lt;^&gt;app_name_or_id&lt;^&gt;

				
			

Перезапустите приложение:

				
					
pm2 restart &lt;^&gt;app_name_or_id&lt;^&gt;

				
			

Выведем список приложений, управление которыми осуществляет PM2:

				
					
pm2 list

				
			

Получим информацию об определенном приложении по имени приложения:

				
					
pm2 info &lt;^&gt;app_name&lt;^&gt;

				
			

Монитор процесса 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/&lt;^&gt;example.com&lt;^&gt;

				
			

В блоке server должен содержаться блок location /. Замените содержимое этого блока следующей конфигурацией. Если ваше приложение настроено для прослушивания другого порта, измените номер порта в выделенной части на подходящий:

				
					
[label /etc/nginx/sites-available/example.com]

server {

...

 location / {

 proxy_pass http://localhost:&lt;^&gt;3000&lt;^&gt;;

 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 /&lt;^&gt;app2&lt;^&gt; {

 proxy_pass http://localhost:&lt;^&gt;3001&lt;^&gt;;

 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 20.04. Настройка обратного прокси-сервера достаточно гибкая, чтобы предоставить вашим пользователям доступ к другим приложениям или статическому веб-контенту, который вы хотите опубликовать.