如何在 Ubuntu 20.04 上设置用于生产的 Node.js 应用程序

介绍

Node.js是用于构建服务器端和网络应用程序的开源 JavaScript 运行时环境。该平台可在 Linux、macOS、FreeBSD 和 Windows 上运行。尽管您可以在命令行中运行 Node.js 应用程序,但本教程将重点介绍将它们作为服务运行。这意味着它们将在重启或失败时重新启动,并且可以安全地在生产环境中使用。

在本教程中,您将在单个 Ubuntu 20.04 服务器上设置生产就绪的 Node.js 环境。该服务器将运行由PM2管理的 Node.js 应用程序,并通过 Nginx 反向代理为用户提供对应用程序的安全访问。Nginx 服务器将使用Let’s Encrypt提供的免费证书提供 HTTPS

先决条件

本指南假设您具备以下条件:

完成先决条件后,您将拥有一台服务器,在 处为您的域的默认占位符页面提供服务https://example.com/

第 1 步 – 安装 Node.js

让我们从使用NodeSource包存档安装最新的 LTS 版本的 Node.js 开始

首先,安装 NodeSource PPA 以访问其内容。确保您位于主目录中,并用于curl从其存档中检索最新 LTS 版本的 Node.js 的安装脚本。

  • cd ~
  • curl -sL https://deb.nodesource.com/setup_14.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 版本,请键入:

  • node -v
Output
v14.4.0

注意:从 NodeSource PPA 安装时,Node.js 可执行文件被称为nodejs,而不是node

nodejs包包含nodejs二进制文件以及npmNode 模块的包管理器,因此您无需npm单独安装

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

  • npm -v
Output
6.14.5

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

  • sudo apt install build-essential

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

安装 Node.js 运行时后,让我们继续编写 Node.js 应用程序。

第 2 步 – 创建一个 Node.js 应用程序

让我们编写一个Hello World应用程序,它向任何 HTTP 请求返回“Hello World”。此示例应用程序将帮助您设置 Node.js。您可以将其替换为您自己的应用程序 — 只需确保修改您的应用程序以侦听适当的 IP 地址和端口。

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

  • cd ~
  • nano hello.js

在文件中插入以下代码:

〜/你好.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}/`);
});

保存文件并退出编辑器。

此 Node.js 应用程序侦听指定的地址 ( localhost) 和端口 ( 3000),并返回“Hello World!” 带有200HTTP 成功代码。由于我们正在侦听localhost,远程客户端将无法连接到我们的应用程序。

要测试您的应用程序,请键入:

  • node hello.js

您将收到以下输出:

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

注意:以这种方式运行 Node.js 应用程序将阻止其他命令,直到应用程序被按下 杀死CTRL+C

要测试应用程序,打开你的服务器上的另一个终端会话,并连接到localhostcurl

  • curl http://localhost:3000

如果您得到以下输出,则应用程序正常运行并侦听正确的地址和端口:

Output
Hello World!

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

一旦您确定它正在工作,请按 终止该应用程序(如果您还没有)CTRL+C

步骤 3 — 安装 PM2

接下来让我们安装 PM2,一个 Node.js 应用程序的进程管理器。PM2 使守护程序成为可能,以便它们作为服务在后台运行。

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

  • sudo npm install pm2@latest -g

-g选项告诉全局npm安装模块,以便它在系统范围内可用。

让我们首先使用该pm2 start命令hello.js在后台运行您的应用程序

  • 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 自动分配一个App name(基于文件名,没有.js扩展名)和一个 PM2 idPM2 还维护其他信息,例如PID进程的状态、当前状态和内存使用情况。

如果应用程序崩溃或被杀死,在 PM2 下运行的应用程序将自动重新启动,但我们可以采取额外的步骤来使用startup子命令在系统启动时启动应用程序此子命令生成并配置启动脚本以在服务器启动时启动 PM2 及其托管进程:

  • pm2 startup systemd

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

Output
[PM2] Init System found: systemd sammy [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 sammy --hp /home/sammy

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

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

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

  • pm2 save

您现在已经创建了一个在启动时为您的用户运行的 systemd单元pm2这个pm2实例反过来运行hello.js.

使用以下命令启动服务systemctl

  • sudo systemctl start pm2-sammy

如果此时您遇到错误,您可能需要重新启动,您可以使用sudo reboot.

检查 systemd 单元的状态:

  • systemctl status pm2-sammy

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

除了我们已经介绍过的那些之外,PM2 还提供了许多子命令,允许您管理或查找有关您的应用程序的信息。

使用此命令停止应用程序(指定 PM2App nameid):

  • pm2 stop app_name_or_id

重新启动应用程序:

  • pm2 restart app_name_or_id

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

  • pm2 list

使用其获取有关特定应用程序的信息App name

  • pm2 info app_name

PM2 进程监视器可以通过monit子命令拉起这将显示应用程序状态、CPU 和内存使用情况:

  • pm2 monit

请注意,pm2不带任何参数运行也会显示一个包含示例用法的帮助页面。

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

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

您的应用程序正在运行并侦听localhost,但您需要为您的用户设置访问它的方式。为此,我们将 Nginx Web 服务器设置为反向代理。

在先决条件教程中,您在文件中设置了 Nginx 配置打开此文件进行编辑:/etc/nginx/sites-available/example.com

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

server块内,您​​应该有一个现有location /块。使用以下配置替换该块的内容。如果您的应用程序设置为侦听不同的端口,请将突出显示的部分更新为正确的端口号:

/etc/nginx/sites-available/example.com
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;
    }
...
}

这将配置服务器以响应其根上的请求。假设我们的服务器可在example.com,访问通过网络浏览器会发送请求到,侦听端口https://example.com/hello.js3000localhost

您可以location向同一服务器块添加其他块,以提供对同一服务器上其他应用程序的访问。例如,如果您还在 port 上运行另一个 Node.js 应用程序3001,您可以添加此位置块以允许通过以下方式访问它https://example.com/app2

/etc/nginx/sites-available/example.com — 可选
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 地址或域名)来尝试一下。

结论

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

觉得文章有用?

点个广告表达一下你的爱意吧 !😁