如何在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服务。
先决条件 jué
在进行本指南之前,假设您具备以下条件:
- A Rocky Linux 9 server setup, as described in the initial server setup guide for Rocky Linux 9. You should have a non-root user with sudo privileges and an active firewall.
- A domain name pointed at your server’s public IP. This tutorial will use the domain name example.com throughout.
- Nginx installed, as covered in How To Install Nginx on Rocky Linux 9.
- Nginx configured with SSL using Let’s Encrypt certificates. How To Secure Nginx with Let’s Encrypt on Rocky Linux 9 will walk you through the process.
- Node.js installed on your server. How To Install Node.js on Rocky Linux 9
当您完成先决条件后,您将在https://example.com/上拥有一个为您的域名提供默认占位页面的服务器。
第一步 — 创建一个 Node.js 应用程序
让我们编写一个Hello World的应用程序,它会对任何HTTP请求返回“Hello World”。这个示例应用程序将帮助您开始使用Node.js。您可以将其替换为自己的应用程序,只需确保修改应用程序以侦听适当的IP地址和端口。
Rocky Linux 9自带的默认文本编辑器是vi。vi是一个非常强大的文本编辑器,但对于没有经验的用户来说,可能会有些复杂。您可能希望安装一个更用户友好的编辑器,比如nano,以便在您的Rocky Linux 9服务器上编辑配置文件。
- sudo dnf install nano
现在,使用nano或您最喜欢的文本编辑器,创建一个名为hello.js的示例应用程序。
- nano 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应用程序监听指定的地址(本地主机)和端口(3000),并以200 HTTP成功代码返回“Hello World!”。由于我们在本地主机上监听,远程客户端无法连接到我们的应用程序。
要测试您的应用程序,请输入:
- node hello.js
你将会收到以下的输出结果。
Server running at http://localhost:3000/
Note
为了测试应用程序,在您的服务器上打开另一个终端会话,并通过curl连接到本地主机。
- curl http://localhost:3000
如果您得到以下输出,则表示应用程序正常工作并正在正确的地址和端口上进行监听:
Hello World!
如果您没有得到预期的输出,请确保您的Node.js应用程序正在运行并配置为在正确的地址和端口上侦听。
确认应用程序正常运行后,按下CTRL+C键关闭应用程序(如果你还没有关闭的话)。
第二步-安装PM2
接下来,让我们安装PM2,这是一个用于Node.js应用程序的进程管理器。PM2可以将应用程序设为守护进程,使其作为后台服务一直运行。
使用npm在你的服务器上安装最新版本的PM2。
- sudo npm install pm2@latest -g
-g选项告诉npm在全局安装该模块,使其在整个系统范围内可用。
让我们首先使用pm2 start命令在后台运行你的应用程序hello.js。
- pm2 start hello.js
这也会将您的应用程序添加到PM2的进程列表中,每次启动应用程序时会输出该列表。
… [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下运行,如果应用程序崩溃或被杀死,它将自动重新启动。但是,我们可以采取额外的步骤,使用启动子命令来在系统启动时启动应用程序。这个命令会生成并配置一个启动脚本,以在服务器启动时启动PM2及其管理的进程。
- pm2 startup systemd
… [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工具时出现权限问题)。
- sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy –hp /home/sammy
… [ ‘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文件。
- sudo nano /etc/systemd/system/pm2-sammy.service
在配置文件的[Service]块中,将PIDFile设置的内容替换为/run/pm2.pid,并添加另一个高亮显示的Environment行。
[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启动服务。
- sudo systemctl start pm2-sammy
查看systemd单元的状态
- systemctl status pm2-sammy
要详细了解systemd,请查阅《Systemd Essentials: Working with Services, Units, and the Journal》。
除了我们已经涵盖的内容之外,PM2还提供了许多子命令,可以让您管理或查询有关您的应用程序的信息。
使用该命令停止一个应用程序(请指定PM2应用的名称或ID)
- pm2 stop app_name_or_id
重启一个应用程序:
- pm2 restart app_name_or_id
列出当前由PM2管理的应用程序。
- pm2 list
使用应用名称获取有关特定应用程序的信息。
- pm2 info app_name
可以使用monit子命令调出PM2进程监视器。这将显示应用程序的状态、CPU和内存使用情况。
- pm2 monit
请注意,运行pm2时不带任何参数也会显示帮助页面及示例用法。
既然你的Node.js应用程序正在运行并由PM2管理,那么让我们设置反向代理。
第三步-将Nginx设置为反向代理服务器
你的应用正在本地运行和监听,但是你需要设置一个方式让用户访问它。我们将设置Nginx作为反向代理服务器来实现这个目的。
在先决教程中,你需要在 /etc/nginx/conf.d/your_domain.conf 文件中设置你的 Nginx 配置。打开这个文件进行编辑。
- sudo nano /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上可用,通过 web 浏览器访问 https://your_domain/ 会将请求发送到位于本地主机的监听端口 3000 的 hello.js。
你可以在同一个服务器块中添加额外的位置块,以便让其他应用程序在同一服务器上获得访问权限。例如,如果你还在3001端口上运行另一个Node.js应用程序,你可以添加这个位置块来通过https://你的域名/app2访问它。
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;
}
...
}
完成添加应用程序的位置模块后,请保存文件并退出编辑器。
请确保您在打字时没有引入任何语法错误。
- sudo nginx -t
重启Nginx:
- sudo systemctl restart nginx
假设您的Node.js应用程序正在运行,且应用程序和Nginx的配置正确,您现在应该能够通过Nginx反向代理访问您的应用程序。尝试通过访问服务器的URL(公共IP地址或域名)来验证。
结论
恭喜!您现在已经在一个Rocky Linux 9服务器上使用Nginx反向代理运行您的Node.js应用程序。这个反向代理设置足够灵活,可以让您的用户访问您想分享的其他应用程序或静态网络内容。
接下来,您可能想了解如何使用Docker构建Node.js应用程序。