如何在 Debian 9 上为生产设置 Node.js 应用程序

介绍

Node.js是一个开源的JavaScript运行环境,用于构建服务器侧和网络应用程序. 该平台运行在Linux,macOS,FreeBSD和Windows上. 虽然您可以在命令行运行Node.js应用程序,但本教程将专注于将它们作为服务运行。

在本教程中,您将在单一的 Debian 9 服务器上设置一个生产准备的 Node.js 环境,该服务器将运行由 PM2管理的 Node.js 应用程序,并通过 Nginx反向代理提供用户安全访问该应用程序。

前提条件

本指南假定您有以下内容:

当您完成前提条件后,您将有一个服务器来服务您的域的默认位置主页在https://example.com/`。

步骤 1 – 安装 Node.js

让我们先安装 Node.js 的最新 LTS 版本,使用 NodeSource包存档。

要安装 NodeSource PPA 并访问其内容,您首先需要更新您的包索引并安装 curl:

1sudo apt update
2sudo apt install curl

请确保您在您的主目录中,然后使用弯曲来获取 Node.js 8.x 档案的安装脚本:

1cd ~
2curl -sL https://deb.nodesource.com/setup_8.x -o nodesource_setup.sh

您可以通过nano或您的 偏好文本编辑器检查本脚本的内容:

1nano nodesource_setup.sh

当你完成检查脚本时,在sudo下运行它:

1sudo bash nodesource_setup.sh

PPA 将被添加到您的配置中,您的本地包缓存将自动更新。从 Nodesource 运行安装脚本后,您可以安装 Node.js 包:

1sudo apt install nodejs

要检查在这些初步步骤后安装了哪个版本的 Node.js,请键入:

1nodejs -v
1[secondary_label Output]
2v8.11.4

<$>[注] 注: 在从 NodeSource PPA 安装时,Node.js 可执行程序被称为nodejs,而不是node

nodejs包包含了nodejs二进制以及npm(https://www.npmjs.com/),它是Node模块的包管理器,因此您不需要单独安装npm

npm 使用您的主目录中的配置文件来跟踪更新. 它将创建在您首次运行 npm. 执行此命令以验证 npm 已安装并创建配置文件:

1npm -v
1[secondary_label Output]
25.6.0

为了使某些npm包工作(例如需要编译源代码的包),您需要安装build-essential包:

1sudo apt install build-essential

您现在有必要的工具来处理需要编译源代码的npm包。

有了 Node.js 运行时间安装,让我们继续写一个 Node.js 应用程序。

步骤 2 — 创建 Node.js 应用程序

让我们写一个 Hello World 应用程序,该应用程序会返回任何 HTTP 请求的Hello World。这个样本应用程序将帮助您设置 Node.js。

首先,让我们创建一个名为hello.js的样本应用程序:

1cd ~
2nano hello.js

将以下代码插入到文件中:

 1[label ~/hello.js]
 2const http = require('http');
 3
 4const hostname = 'localhost';
 5const port = 3000;
 6
 7const server = http.createServer((req, res) => {
 8  res.statusCode = 200;
 9  res.setHeader('Content-Type', 'text/plain');
10  res.end('Hello World!\n');
11});
12
13server.listen(port, hostname, () => {
14  console.log(`Server running at http://${hostname}:${port}/`);
15});

保存文件并离开编辑器。

这个 Node.js 应用程序在指定的地址(‘localhost’)和端口(‘3000’)上收听,并以‘200’ HTTP 成功代码返回Hello World! 因为我们正在收听‘localhost’,所以远程客户端将无法连接到我们的应用程序。

要测试您的应用程序,类型:

1node hello.js

您将看到以下结果:

1[secondary_label Output]
2Server running at http://localhost:3000/

<$>[注] 注: 以这种方式运行 Node.js 应用程序将阻止额外的命令,直到应用程序通过点击 CTRL+C 被杀死。

要测试该应用程序,请在您的服务器上打开另一个终端会话,并使用curl连接到localhost:

1[environment second]
2curl http://localhost:3000

如果您看到以下输出,应用程序正在正常工作,并在正确的地址和端口上收听:

1[secondary_label Output]
2[environment second]
3Hello World!

如果您看不到预期的输出,请确保您的 Node.js 应用程序运行并配置为听取正确的地址和端口。

一旦你确定它工作,杀死应用程序(如果你还没有)通过按CTRL+C

步骤三:安装PM2

接下来,让我们安装 PM2,用于 Node.js 应用程序的流程管理器。

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

1sudo npm install pm2@latest -g

-g选项告诉npm在全球范围内安装模块,因此它可以在整个系统中使用。

让我们先使用pm2 start命令在背景中运行您的应用程序hello.js:

1pm2 start hello.js

这还会将您的应用程序添加到 PM2 的流程列表中,该列表每次启动应用程序时都会输出:

 1[secondary_label Output]
 2[PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2
 3[PM2] PM2 Successfully daemonized
 4[PM2] Starting /home/sammy/hello.js in fork_mode (1 instance)
 5[PM2] Done.
 6┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬───────┬──────────┐
 7│ App name │ id │ mode │ pid  │ status │ restart │ uptime │ cpu │ mem       │ user  │ watching │
 8├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼───────┼──────────┤
 9│ hello    │ 0  │ fork │ 1338 │ online │ 0       │ 0s     │ 0%  │ 23.0 MB   │ sammy │ disabled │
10└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴───────┴──────────┘
11 Use `pm2 show <id|name>` to get more details about an app

正如您所看到的,PM2 会自动分配一个应用名称(基于文件名,不含.js扩展)和一个 PM2 id

如果应用程序故障或被杀死,在PM2下运行的应用程序将自动重新启动,但我们可以采取额外的步骤,通过startup子命令将应用程序启动到系统启动上。

1pm2 startup systemd

结果输出的最后一行将包含一个命令以超级用户权限运行,以设置PM2开始启动:

1[secondary_label Output]
2[PM2] Init System found: systemd
3[PM2] To setup the Startup Script, copy/paste the following command:
4sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

从输出中运行命令,使用您的用户名代替sammy:

1sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

作为一个额外的步骤,我们可以保存 PM2 流程列表和相应的环境:

1pm2 save

您现在已经创建了一个 systemd unit,该实例为您的启动用户运行pm2

使用systemctl开始服务:

1sudo systemctl start pm2-sammy

检查系统d 单元的状态:

1systemctl status pm2-sammy

有关 systemd 的详细概述,请参阅 Systemd Essentials: Working with Services, Units, and the Journal

除了我们所涵盖的,PM2还提供许多子命令,允许您管理或搜索有关您的应用程序的信息。

使用此命令停止应用程序(指定PM2应用程序名称id):

1pm2 stop app_name_or_id

重新启动应用程序:

1pm2 restart app_name_or_id

列出目前由 PM2 管理的应用程序:

1pm2 list

使用其应用名称获取有关特定应用程序的信息:

1pm2 info app_name

PM2 流程监视器可以通过monit子命令拉上,显示应用程序状态、CPU 和内存使用量:

1pm2 monit

请注意,在没有任何参数的情况下运行pm2也会显示有示例使用的帮助页面。

现在您的 Node.js 应用程序正在运行并由 PM2 管理,让我们设置反向代理。

步骤 4 — 将 Nginx 设置为反向代理服务器

您的应用程序正在运行并听到本地主机,但您需要为您的用户设置一种访问方式,我们将为此设置 Nginx 网页服务器作为反向代理。

在前提教程中,您将您的 Nginx 配置设置为 /etc/nginx/sites-available/example.com 文件。

1sudo nano /etc/nginx/sites-available/example.com

服务器区块中,你应该有一个现有的位置/区块,用以下配置来替换该区块的内容,如果你的应用程序设置为在不同的端口上收听,请将突出部分更新到正确的端口号:

 1[label /etc/nginx/sites-available/example.com]
 2server {
 3...
 4    location / {
 5        proxy_pass http://localhost:3000;
 6        proxy_http_version 1.1;
 7        proxy_set_header Upgrade $http_upgrade;
 8        proxy_set_header Connection 'upgrade';
 9        proxy_set_header Host $host;
10        proxy_cache_bypass $http_upgrade;
11    }
12...
13}

假设我们的服务器在example.com上可用,通过网页浏览器访问https://example.com/将请求发送到hello.js,在localhost端口3000上聆听。

您可以将额外的位置块添加到相同的服务器块中,以便提供在相同的服务器上其他应用程序的访问。例如,如果您也在端口3001上运行另一个 Node.js 应用程序,您可以添加此位置块,以便通过https://example.com/app2访问它:

 1[label /etc/nginx/sites-available/example.com — Optional]
 2server {
 3...
 4    location /app2 {
 5        proxy_pass http://localhost:3001;
 6        proxy_http_version 1.1;
 7        proxy_set_header Upgrade $http_upgrade;
 8        proxy_set_header Connection 'upgrade';
 9        proxy_set_header Host $host;
10        proxy_cache_bypass $http_upgrade;
11    }
12...
13}

完成为您的应用程序添加位置块后,保存文件并退出编辑器。

确保您没有输入任何语法错误,键入:

1sudo nginx -t

重新启动 Nginx:

1sudo systemctl restart nginx

假设您的 Node.js 应用程序正在运行,您的应用程序和 Nginx 配置是正确的,您现在应该能够通过 Nginx 反向代理程序访问您的应用程序。

结论

恭喜您!您现在有您的 Node.js 应用程序在 Debian 9 服务器上运行 Nginx 反向代理程序后面,此反向代理程序设置足够灵活,可以让您的用户访问您想要共享的其他应用程序或静态 Web 内容。

Published At
Categories with 技术
comments powered by Disqus