Поиск по сайту:

Как настроить приложение Node.js для работы в CentOS 7


Введение

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

В этом руководстве мы рассмотрим настройку готовой к работе среды Node.js, состоящей из двух серверов CentOS 7; на одном сервере будут запускаться приложения Node.js, управляемые PM2, а другой предоставит пользователям доступ к приложению через обратный прокси-сервер Nginx к серверу приложений.

Версию этого руководства для Ubuntu можно найти здесь.

Предпосылки

В этом руководстве используются два сервера CentOS 7 с частной сетью (в одном центре обработки данных). Частную сеть можно настроить на новых серверах при их создании (в разделе Выберите дополнительные параметры). Мы будем называть их следующими именами:

  • приложение: сервер, на котором мы установим среду выполнения Node.js, ваше приложение Node.js и PM2.
  • web: сервер, на котором мы установим веб-сервер Nginx, который будет действовать как обратный прокси-сервер для вашего приложения. Пользователи получат доступ к общедоступному IP-адресу этого сервера, чтобы получить доступ к вашему приложению Node.js.

Примечание. Обратитесь к документации DigitalOcean — Как включить частную сеть в каплях, если вы собираетесь использовать существующий сервер, на котором в настоящее время не настроена частная сеть.

Прежде чем приступить к работе с этим руководством, у вас должен быть обычный пользователь без полномочий root с привилегиями sudo, настроенный на обоих ваших серверах — это пользователь, под которым вы должны войти на свои серверы. Вы можете узнать, как настроить учетную запись обычного пользователя, следуя нашему руководству по начальной настройке сервера для CentOS 7.

Команды, выполняемые на сервере приложений:

  1. an_example_command_on_app

Команды, выполняемые на веб-сервере:

  1. an_example_command_on_web

Для этого руководства можно использовать один сервер, но вам придется внести несколько изменений по пути. Просто используйте IP-адрес локального хоста, например 127.0.0.1, везде, где используется частный IP-адрес сервера приложений.

Вот диаграмма того, какой будет ваша установка после выполнения этого руководства:

Если вы хотите иметь доступ к своему веб-серверу через доменное имя, а не через общедоступный IP-адрес, купите доменное имя и следуйте этим инструкциям:

  • Как настроить имя хоста в DigitalOcean
  • Как указать серверы имен DigitalOcean от общих регистраторов доменов

Начнем с установки среды выполнения Node.js на сервер приложений.

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

Мы установим последнюю версию LTS Node.js на сервер приложений.

SSH к вашему серверу приложений, используя обычного пользователя без полномочий root с привилегиями sudo.

На сервере приложений воспользуемся curl для загрузки файла конфигурации NodeSource RPM Repository:

  1. curl -L -o nodesource_setup.sh https://rpm.nodesource.com/setup_10.x

CURL будет использовать протокол HTTPS для загрузки сценария установки на ваш сервер, при этом вывод будет включать информацию, относящуюся к загрузке:

Output
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 11109 100 11109 0 0 70128 0 --:--:-- --:--:-- --:--:-- 70757

Затем вы должны проверить содержимое скрипта. Следующая команда откроет сценарий установки NodeSource в консоли вашего сервера, который вы затем можете сопоставить со сценарием установки NodeSource (из репозитория NodeSource Distributions Github), чтобы подтвердить правильность загрузки сценария:

  1. vi nodesource_setup.sh

Удовлетворившись файлом, выйдите из vi, набрав :q для quit и вернитесь в командную строку.

Теперь давайте запустим скрипт установки, чтобы установить репозиторий NodeSource RPM. Это позволит нам получить доступ к репозиторию NodeSource из менеджера пакетов yum:

  1. sudo -E bash nodesource_setup.sh

Скрипт выводит информацию о настройке для нашей справки:

Output
## Installing the NodeSource Node.js 10.x repo... ## Inspecting system... + rpm -q --whatprovides redhat-release || rpm -q --whatprovides centos-release || rpm -q --whatprovides cloudlinux-release || rpm -q --whatprovides sl-release + uname -m ## Confirming "el7-x86_64" is supported... + curl -sLf -o /dev/null 'https://rpm.nodesource.com/pub_10.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm' ## Downloading release setup RPM... + mktemp + curl -sL -o '/tmp/tmp.2aCcULVx8n' 'https://rpm.nodesource.com/pub_10.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm' ## Installing release setup RPM... + rpm -i --nosignature --force '/tmp/tmp.2aCcULVx8n' ## Cleaning up... + rm -f '/tmp/tmp.2aCcULVx8n' ## Checking for existing installations... + rpm -qa 'node|npm' | grep -v nodesource ## Run `sudo yum install -y nodejs` to install Node.js 10.x and npm. ## You may also need development tools to build native addons: sudo yum install gcc-c++ make ## To install the Yarn package manager, run: curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo sudo yum install yarn

Перед установкой Node.js важно очистить всю кэшированную информацию из yum. Очистка кеша гарантирует, что yum использует сетевое подключение для получения Node.js из нашего нового репозитория NodeSource (что предотвратит любые потенциальные конфликты, вызванные устаревшими пакетами):

  1. sudo yum clean all

Далее мы загрузим и сделаем пригодными для использования все метаданные для включенных в данный момент репозиториев yum. Это обеспечит максимально быстрое выполнение наших запросов yum:

  1. sudo yum makecache fast

Чтобы скомпилировать и установить собственные надстройки из npm, нам также необходимо установить инструменты сборки:

  1. sudo yum install -y gcc-c++ make

Теперь мы можем установить последнюю версию пакета Node.js:

  1. sudo yum install -y nodejs

Убедитесь, что Node установлен, проверив его версию с помощью этой команды:

  1. node -v

Ваш вывод покажет номер версии, которую вы используете:

Output
v10.16.3

Теперь среда выполнения Node.js установлена и готова к запуску приложения. Давайте напишем приложение Node.js.

Шаг 2 — Создание приложения Node.js

Теперь мы создадим приложение Hello World, которое просто возвращает Hello World на любые HTTP-запросы. Это пример приложения, которое поможет вам настроить Node.js, который вы можете заменить своим собственным приложением — просто убедитесь, что вы изменили свое приложение, чтобы прослушивать соответствующие IP-адреса и порты.

Поскольку мы хотим, чтобы наше приложение Node.js обслуживало запросы, поступающие с нашего обратного прокси-сервера (веб), мы будем использовать частный сетевой интерфейс нашего сервера приложений для связи между серверами. Найдите частный сетевой адрес вашего сервера приложений.

Если вы используете дроплет DigitalOcean в качестве своего сервера, вы можете найти частный IP-адрес сервера через службу Метаданные. На сервере приложений используйте команду curl, чтобы получить IP-адрес прямо сейчас:

  1. curl -sw "\n" http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address

Вы захотите скопировать вывод (частный IP-адрес), так как он будет использоваться для настройки приложения Node.js.

Затем создайте и откройте приложение Node.js для редактирования. В этом руководстве мы будем использовать vi для редактирования примера приложения с именем hello.js:

  1. vi hello.js

Вставьте следующий код в файл и обязательно замените частный IP-адрес сервера приложений на оба выделенных элемента APP_PRIVATE_IP_ADDRESS. При желании вы также можете заменить выделенный порт 8080 в обоих местах (обязательно используйте порт без прав администратора, т. е. 1024 или больше):

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(8080, 'APP_PRIVATE_IP_ADDRESS');
console.log('Server running at http://APP_PRIVATE_IP_ADDRESS:8080/');

Теперь сохраните и выйдите, нажав ESC для выхода из режима --INSERT--, а затем :wq для записи и выход в одной команде.

Это приложение Node.js просто прослушивает указанный IP-адрес и порт и возвращает Hello World с HTTP-кодом успеха 200. Это означает, что приложение доступно только с серверов в той же частной сети, например, с нашего веб-сервера.

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

  1. node hello.js

Примечание. Запуск приложения Node.js таким образом блокирует дополнительные команды до тех пор, пока приложение не будет завершено нажатием CTRL+C.

Это сэкономит много времени на отладку Nginx, если мы сначала проверим, что наш веб-сервер может взаимодействовать с приложением Node.js в приложении.

Чтобы протестировать приложение, откройте другой сеанс терминала и подключитесь к своему веб-серверу. Поскольку веб-сервер находится в той же частной сети, он должен иметь доступ к частному IP-адресу сервера приложений с помощью curl. Не забудьте заменить частный IP-адрес сервера приложений на APP_PRIVATE_IP_ADDRESS и порт, если вы его изменили:

  1. curl http://APP_PRIVATE_IP_ADDRESS:8080

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

Node Application Output
Hello World

Если вы не видите правильный вывод, убедитесь, что ваше приложение Node.js запущено и настроено для прослушивания правильного IP-адреса и порта.

На сервере приложений обязательно завершите приложение, нажав CTRL+C.

Шаг 3 — Установка и использование PM2

Теперь мы установим PM2, менеджер процессов для приложений Node.js. PM2 предоставляет простой способ управления и демонизации приложений (запуск их как службы).

Мы будем использовать Node Packaged Modules (NPM), который по сути представляет собой менеджер пакетов для модулей Node, устанавливаемых с помощью Node.js, для установки PM2 на наш сервер приложений. Используйте эту команду для установки PM2:

  1. sudo npm install pm2@latest -g

Мы рассмотрим несколько основных способов использования PM2.

Первое, что вам нужно сделать, это использовать команду pm2 start для запуска приложения hello.js в фоновом режиме:

  1. pm2 start hello.js

Это также добавит ваше приложение в список процессов PM2, который выводится каждый раз, когда вы запускаете приложение:

Output
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────────────┬──────────┐ │ App name │ id │ mode │ pid │ status │ restart │ uptime │ memory │ watching │ ├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────────────┼──────────┤ │ hello │ 0 │ fork │ 30099 │ online │ 0 │ 0s │ 14.227 MB │ disabled │ └──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────────────┴──────────┘

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

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

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

  1. sudo pm2 startup systemd

Вы увидите следующий вывод, указывающий на то, что служба PM2 установлена:

Output
[PM2] Generating system init script in /etc/systemd/system/pm2.service [PM2] Making script booting at startup... [PM2] -systemd- Using the command: su root -c "pm2 dump && pm2 kill" && su root -c "systemctl daemon-reload && systemctl enable pm2 && systemctl start pm2" [PM2] Dumping processes [PM2] Stopping PM2... [PM2] All processes have been stopped and deleted [PM2] PM2 stopped [PM2] Done.

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

  1. pm2 save

Вы увидите следующий вывод, который указывает на то, что список процессов PM2 был сохранен:

Output
[PM2] Saving current process list... [PM2] Successfully saved in /home/deployer/.pm2/dump.pm2

Теперь ваши приложения, управляемые PM2, должны запускаться автоматически при загрузке.

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

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

  1. pm2 stop example

Перезапустите приложение этой командой (укажите PM2 Имя приложения или id):

  1. pm2 restart example

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

  1. pm2 list

Дополнительную информацию о конкретном приложении можно найти с помощью подкоманды info (укажите имя приложения или id PM2):

  1. pm2 info example

Монитор процессов PM2 можно вызвать с помощью подкоманды monit. Это отображает состояние приложения, ЦП и использование памяти:

  1. pm2 monit

Примечание. Выполнение команды monit PM2 заблокирует дополнительные команды до тех пор, пока приложение не будет уничтожено нажатием CTRL+C.

Теперь, когда ваше приложение Node.js запущено и управляется PM2, давайте настроим обратный прокси-сервер.

Шаг 4 — Настройка обратного прокси-сервера Nginx

Теперь, когда ваше приложение запущено и прослушивает частный IP-адрес, вам нужно настроить способ доступа к нему для ваших пользователей. Для этой цели мы настроим веб-сервер Nginx в качестве обратного прокси-сервера. В этом руководстве мы настроим сервер Nginx с нуля. Если у вас уже есть настроенный сервер Nginx, вы можете просто скопировать блок location в блок сервера по вашему выбору (убедитесь, что местоположение не конфликтует ни с каким существующим содержимым вашего веб-сервера).

На веб-сервере установим пакет epel-release с помощью yum:

  1. sudo yum install epel-release

Затем установите Nginx:

  1. sudo yum install nginx

Теперь откройте файл конфигурации Nginx для редактирования:

  1. sudo vi /etc/nginx/nginx.conf

Сначала найдите строку, в которой определено server_name, в блоке server по умолчанию. Это должно выглядеть примерно так:

server_name _;

Обновите имя сервера, заменив символ подчеркивания (_) своим собственным доменным именем в директиве server_name (или IP-адресом, если у вас не настроен домен).

server_name your-domain;

Затем найдите строку, в которой определяется location / (обычно на несколько строк ниже server_name), в том же блоке сервера по умолчанию. Это должно выглядеть примерно так:

        location / {
        }

Замените его следующим блоком кода и обязательно замените APP_PRIVATE_IP_ADDRESS частным IP-адресом сервера приложений. Кроме того, измените порт (8080), если ваше приложение настроено на прослушивание другого порта:

    location / {
        proxy_pass http://APP_PRIVATE_IP_ADDRESS:8080;
        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;
    }

Это настраивает веб-сервер для ответа на запросы в его корне. Предполагая, что наш сервер доступен по адресу ваш-домен, при доступе к http://ваш-домен/ через веб-браузер будет отправлен запрос на частный IP-адрес сервера приложений на порту 8080, который будет получен и отправлен приложением Node.js.

Вы можете добавить дополнительные блоки location в тот же блок сервера, чтобы обеспечить доступ к другим приложениям на том же веб-сервере. Например, если вы также запускали другое приложение Node.js на сервере приложений через порт 8081, вы можете добавить этот блок местоположения, чтобы разрешить доступ к нему через http://ваш-домен. /приложение2:

    location /app2 {
        proxy_pass http://APP_PRIVATE_IP_ADDRESS:8081;
        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;
    }

После того, как вы закончите редактирование блока (блоков) местоположения для вашего приложения (я), сохраните и выйдите, нажав ESC, чтобы выйти из режима --INSERT--, а затем :wq, чтобы написать и выйти в одной команде.

На веб-сервере перезапустите Nginx:

  1. sudo systemctl start nginx

Далее мы хотим убедиться, что Nginx запускается при каждом перезапуске сервера:

  1. sudo systemctl enable nginx

Команда enable должна предоставить следующий вывод

Output
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

Вы также можете убедиться, что Nginx запущен и включен, запросив его статус у systemctl:

  1. sudo systemctl status nginx

Команда состояния выведет информацию о конфигурации для службы Nginx:

Output
● nginx.service - The nginx HTTP and reverse proxy server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled) Active: active (running) since Mon 2019-10-14 09:37:23 UTC; 3min 29s ago Main PID: 12818 (nginx) CGroup: /system.slice/nginx.service ├─12818 nginx: master process /usr/sbin/nginx └─12819 nginx: worker process Oct 14 09:37:23 centos-s-1vcpu-1gb-sgp1-01 systemd[1]: Starting The nginx HTTP and reverse proxy server... Oct 14 09:37:23 centos-s-1vcpu-1gb-sgp1-01 nginx[12814]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok Oct 14 09:37:23 centos-s-1vcpu-1gb-sgp1-01 nginx[12814]: nginx: configuration file /etc/nginx/nginx.conf test is successful Oct 14 09:37:23 centos-s-1vcpu-1gb-sgp1-01 systemd[1]: Failed to read PID from file /run/nginx.pid: Invalid argument Oct 14 09:37:23 centos-s-1vcpu-1gb-sgp1-01 systemd[1]: Started The nginx HTTP and reverse proxy server.

Наконец, предоставьте Nginx возможность ретрансляции трафика через Security-Enhanced Linux (SELinux). SELinux обеспечивает уровень безопасности, реализующий обязательный контроль доступа (MAC) в ядре Linux. Каждый объект операционной системы (процесс, дескриптор файла, файл и т. д.) помечен контекстом SELinux, который определяет разрешения и операции, которые может выполнять объект.

Nginx помечен контекстом httpd_t и, как следствие, имеет ряд конфигураций, заблокированных SELinux, если это явно не разрешено. Чтобы продемонстрировать это, выполните следующую команду, чтобы убедиться, что служба Nginx помечена как httpd_t:

  1. ps -eZ

Эта команда предоставляет информацию о состоянии процесса, найдите информацию о конкретном процессе Nginx, чтобы увидеть метку. Вы увидите httpd_t аналогично следующему:

Output
... system_u:system_r:httpd_t:s0 10208 ? 00:00:00 nginx system_u:system_r:httpd_t:s0 10209 ? 00:00:00 nginx ...

Теперь давайте проверим состояние логических значений по умолчанию, связанных с меткой httpd_t SELinux. Мы можем показать эту информацию, выполнив следующую команду:

  1. getsebool -a

В этом руководстве нас интересуют только логические значения, связанные с httpd:

Output
... httpd_anon_write --> off httpd_builtin_scripting --> on httpd_can_check_spam --> off httpd_can_connect_ftp --> off httpd_can_connect_ldap --> off httpd_can_connect_mythtv --> off httpd_can_connect_zabbix --> off httpd_can_network_connect --> off httpd_can_network_connect_cobbler --> off httpd_can_network_connect_db --> off httpd_can_network_memcache --> off httpd_can_network_relay --> off httpd_can_sendmail --> off httpd_dbus_avahi --> off httpd_dbus_sssd --> off httpd_dontaudit_search_dirs --> off httpd_enable_cgi --> on httpd_enable_ftp_server --> off httpd_enable_homedirs --> off httpd_execmem --> off httpd_graceful_shutdown --> on httpd_manage_ipa --> off httpd_mod_auth_ntlm_winbind --> off httpd_mod_auth_pam --> off httpd_read_user_content --> off httpd_run_ipa --> off httpd_run_preupgrade --> off httpd_run_stickshift --> off httpd_serve_cobbler_files --> off httpd_setrlimit --> off httpd_ssi_exec --> off httpd_sys_script_anon_write --> off httpd_tmp_exec --> off httpd_tty_comm --> off httpd_unified --> off httpd_use_cifs --> off httpd_use_fusefs --> off httpd_use_gpg --> off httpd_use_nfs --> off httpd_use_openstack --> off httpd_use_sasl --> off httpd_verify_dns --> off ...

Следует особо отметить два логических значения: httpd_can_network_connect и httpd_can_network_relay. Документация Redhat содержит подробную информацию о каждом из логических значений httpd и связанных с ними функциях (если вы хотите узнать больше о каждом логическом значении), хотя ниже приведены пояснения двух логических значений, относящихся к этому руководству:

...
httpd_can_network_connect: When disabled, this Boolean prevents HTTP scripts and modules from initiating a connection to a network or remote port. Enable this Boolean to allow this access.
httpd_can_network_relay: Enable this Boolean when httpd is being used as a forward or reverse proxy.
...

Поскольку наша конфигурация предназначена только для ретрансляции трафика, нам просто нужно сообщить SELinux, что сервер httpd, в нашем случае Nginx, может использовать сеть для ретрансляции трафика в настроенной нами конфигурации обратного прокси-сервера. Мы будем использовать флаг -P, чтобы гарантировать, что изменения будут постоянными (опускание этого флага приведет к тому, что httpd_can_network_relay вернется к своему состоянию по умолчанию, выключенному, после перезапуска сервера ):

  1. sudo setsebool -P httpd_can_network_relay on

Предполагая, что ваше приложение Node.js запущено и ваше приложение и конфигурации Nginx верны, вы сможете получить доступ к своему приложению через обратный прокси-сервер веб-сервера. Попробуйте это, открыв URL-адрес вашего веб-сервера (его общедоступный IP-адрес или доменное имя).

Примечание. Если вы также планировали использовать свой веб-сервер для размещения других сайтов (в качестве обычных виртуальных хостов), вам также необходимо включить параметр httpd_can_network_connect.

Заключение

Теперь у вас есть приложение Node.js, работающее за обратным прокси-сервером Nginx. Эта настройка обратного прокси-сервера достаточно гибкая, чтобы предоставить вашим пользователям доступ к другим приложениям или статическому веб-контенту, которым вы хотите поделиться.

Кроме того, если вы хотите зашифровать передачу между вашим веб-сервером и вашими пользователями, вот руководство, которое поможет вам настроить поддержку HTTPS (TLS/SSL).