如何在Rocky Linux 9上為生產設置Node.js應用程式

介紹

Node.js 是一個用於構建伺服器端和網絡應用程序的開源JavaScript運行時環境。該平台可在Linux、macOS、FreeBSD和Windows上運行。儘管您可以在命令行上運行Node.js應用程序,但本教程將重點介紹如何將它們作為服務運行。這意味著它們將在重新啟動或失敗時重新啟動,並且可以安全地在生產環境中使用。

在本教程中,您將在一個單獨的Rocky Linux 9服務器上設置一個適用於生產的Node.js環境。該服務器將運行一個由PM2管理的Node.js應用程序,並通過Nginx反向代理為用戶提供安全訪問該應用程序。Nginx服務器將使用由Let’s Encrypt提供的免費證書提供HTTPS。

先決條件

本指南假設您具有以下條件:

完成先決條件後,您將在https://example.com/上為您的域名提供默認佔位頁面。

步驟 1 — 創建 Node.js 應用程式

讓我們編寫一個Hello World應用程式,以對任何 HTTP 請求返回“Hello World”。此示例應用程式將幫助您啟動並運行 Node.js。您可以將其替換為您自己的應用程式 —— 只需確保您修改應用程式以聆聽適當的 IP 地址和端口。

Rocky Linux 9 預設的文本編輯器是vivi是一個非常強大的文本編輯器,但對於缺乏經驗的用戶來說可能有些難以理解。您可能希望安裝一個更加用戶友好的編輯器,如nano,以便於編輯 Rocky Linux 9 伺服器上的配置文件:

  1. sudo dnf install nano

現在,使用 nano 或您喜歡的文字編輯器,創建一個名為 hello.js 的示例應用程序:

  1. nano hello.js

將以下代碼插入文件中:

~/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}/`);
});

保存文件並退出編輯器。如果使用 nano,按 Ctrl+X,然後在提示時按 Y,然後按 Enter。

此 Node.js 應用程序在指定的地址(localhost)和端口(3000)上聽取,並返回帶有 200 的“Hello World!” HTTP 成功碼。由於我們正在聽取 localhost,遠程客戶端將無法連接到我們的應用程序。

要測試應用程序,輸入:

  1. node hello.js

您將收到以下輸出:

Output
Server running at http://localhost:3000/

注意:以這種方式運行 Node.js 應用程序將阻止其他命令,直到通過按 CTRL+C 來終止應用程序。

要測試應用程序,在您的服務器上打開另一個終端會話,並使用 curl 連接到 localhost

  1. curl http://localhost:3000

如果您獲得以下輸出,則應用程序正常運行並在正確的地址和端口上聽取:

Output
Hello World!

如果未獲得預期的輸出,請確保您的 Node.js 應用程序正在運行並配置為聽取正確的地址和端口。

確保它正常運行後,通過按 CTRL+C 來終止應用程序(如果尚未終止)。

步驟 2 — 安裝 PM2

接下來讓我們安裝 PM2,這是一個用於 Node.js 應用程式的進程管理器。PM2 可以將應用程式守護起來,讓它們作為服務在背景運行。

使用 npm 在您的伺服器上安裝最新版本的 PM2:

  1. sudo npm install pm2@latest -g

使用 -g 選項告訴 npm 將模組安裝 全域性地,這樣它就可以在整個系統中使用。

讓我們首先使用 pm2 start 命令在背景運行您的應用程式 hello.js

  1. pm2 start hello.js

這也將您的應用程式添加到 PM2 的進程列表中,每次啟動應用程式時都會輸出:

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 自動分配一個 應用程式名稱(根據文件名,不含 .js 擴展名)和一個 PM2 id。PM2 還維護其他信息,例如進程的 PID、當前狀態和內存使用情況。

在 PM2 下運行的應用程式如果崩潰或被終止,將會自動重新啟動,但我們可以採取額外的步驟,使用 startup 子命令讓應用程式在系統啟動時啟動。此子命令會生成並配置一個啟動腳本以在伺服器啟動時啟動 PM2 及其管理的進程:

  1. pm2 startup systemd
Output
… [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

複製並運行提供的命令(這是為了避免以 sudo 運行 Node.js 工具時出現權限問題):

  1. sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
Output
… [ 'systemctl enable pm2-sammy' ] [PM2] Writing init configuration in /etc/systemd/system/pm2-sammy.service [PM2] Making script booting at startup... [PM2] [-] Executing: systemctl enable pm2-sammy... Created symlink /etc/systemd/system/multi-user.target.wants/pm2-sammy.service → /etc/systemd/system/pm2-sammy.service. [PM2] [v] Command successfully executed. +---------------------------------------+ [PM2] Freeze a process list on reboot via: $ pm2 save [PM2] Remove init script via: $ pm2 unstartup systemd

現在,您需要對剛剛生成的系統服務進行編輯,以使其與Rocky Linux的SELinux安全系統兼容。 使用nano或您喜歡的文本編輯器,打開/etc/systemd/system/pm2-sammy.service

  1. sudo nano /etc/systemd/system/pm2-sammy.service

在配置文件的[Service]塊中,將PIDFile設置的內容替換為下面突出顯示的/run/pm2.pid,並添加其他突出顯示的Environment行:

/etc/systemd/system/pm2-sammy.service
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target

[Service]
Type=forking
User=sammy
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/home/sammy/.local/bin:/home/sammy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/home/sammy/.pm2
PIDFile=/run/pm2.pid
Restart=on-failure
Environment=PM2_PID_FILE_PATH=/run/pm2.pid

ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/local/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill

[Install]

保存並關閉文件。您現在已經創建了一個在啟動時為您的用戶運行pm2的systemd 單元。 這個pm2實例又運行hello.js

使用systemctl啟動服務:

  1. sudo systemctl start pm2-sammy

檢查systemd單元的狀態:

  1. systemctl status pm2-sammy

有關systemd的詳細概述,請參閱Systemd基本知識:使用服務、單元和日誌

除了我們已經介紹的內容外,PM2還提供了許多子命令,允許您管理或查找有關應用程序的信息。

使用此命令停止應用程序(指定PM2的應用程序名稱id):

  1. pm2 stop app_name_or_id

重新啟動應用程序:

  1. pm2 restart app_name_or_id

列出PM2當前管理的應用程序:

  1. pm2 list

使用其應用程序名稱獲取有關特定應用程序的信息:

  1. pm2 info app_name

PM2 進程監控器可以使用 monit 子命令拉起。這會顯示應用程序狀態、CPU 和內存使用情況:

  1. pm2 monit

請注意,運行 pm2 而不帶任何參數也會顯示帶有示例用法的幫助頁面。

現在,您的 Node.js 應用程序正在運行並由 PM2 管理,讓我們設置反向代理。

第三步 — 設置 Nginx 為反向代理服務器

您的應用程序正在運行並監聽在 localhost 上,但您需要設置一種方式讓用戶訪問它。我們將設置 Nginx Web 服務器作為反向代理來達到此目的。

在先決教程中,您在 /etc/nginx/conf.d/your_domain.conf 文件中設置了 Nginx 配置。打開此文件進行編輯:

  1. sudo nano /etc/nginx/conf.d/your_domain.conf

server 塊內,您應該有一個現有的 location / 塊。將該塊的內容替換為以下配置。如果您的應用程序設置為監聽不同的端口,請將突出顯示部分更新為正確的端口號:

/etc/nginx/conf.d/your_domain.conf
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;
    }
...
}

這樣配置伺服器以回應位於其根目錄的請求。假設我們的伺服器位於 your_domain,透過網頁瀏覽器訪問 https://your_domain/ 將發送請求至在 localhost 上監聽端口 3000hello.js

您可以在同一伺服器區塊中添加額外的 location 區塊,以提供對同一伺服器上其他應用程序的訪問。例如,如果您還在端口 3001 上運行另一個 Node.js 應用程序,您可以添加此位置區塊以允許通過 https://your_domain/app2 訪問它:

/etc/nginx/conf.d/your_domain.conf — 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;
    }
...
}

在為應用程序添加位置區塊後,請保存文件並退出您的編輯器。

確保您未引入任何語法錯誤,請輸入:

  1. sudo nginx -t

重新啟動 Nginx:

  1. sudo systemctl restart nginx

假設您的 Node.js 應用程序正在運行,且應用程序和 Nginx 配置正確,您現在應該能夠通過 Nginx 反向代理訪問您的應用程序。嘗試通過訪問伺服器的 URL(公共 IP 地址或域名)來測試。

結論

恭喜!您現在已經將您的 Node.js 應用程序運行在 Rocky Linux 9 伺服器的 Nginx 反向代理後。此反向代理設置足夠靈活,可以讓您的用戶訪問其他應用程序或您想共享的靜態網頁內容。

接下來,您可能想了解如何使用Docker建立一個Node.js應用程式。How to build a Node.js application with Docker

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-rocky-linux-9