本教程的先前版本由Brennen Bearnes编写
介绍
Node.js是一个开源JavaScript运行时环境,用于构建服务器端和网络应用程序。 该平台可在Linux,macOS,FreeBSD和Windows上运行。 虽然您可以在命令行运行Node.js应用程序,但本教程将重点介绍如何将它们作为服务运行。 这意味着应用程序将在重新启动或失败时重新启动,并且可以安全地在生产环境中使用。
在本教程中,您将在单个Ubuntu 18.04服务器上设置生产就绪的Node.js环境。 该服务器将运行由PM2管理的Node.js应用程序,并通过Nginx反向代理为用户提供对应用程序的安全访问。 Nginx服务器将使用Let's Encrypt提供的免费证书提供HTTPS。
先决条件
本指南假设您具有以下内容:
- Ubuntu 18.04服务器设置,如Ubuntu 18.04的初始服务器设置指南中所述。 您应该拥有一个具有sudo权限和活动防火墙的非root用户。
- 域名指向服务器的公共IP 。 本教程将始终使用域名example.com 。
- 安装了Nginx,如在Ubuntu 18.04上如何安装Nginx中所述 。
- Nginx使用Let的加密证书配置SSL。 如何使用Ubuntu 18.04上的Let加密来保护Nginx将引导您完成整个过程。
- 端口
3000
上允许连接。 您可以通过运行sudo ufw allow 3000
来启用此功能。 有关UFW的更多信息,请参阅UFW Essentials:通用防火墙规则和命令 。
完成先决条件后,您将有一台服务器在https:// example.com /
提供默认的Nginx占位符页面。
第1步 - 安装Node.js.
让我们首先使用NodeSource包存档安装最新的Node.js LTS版本。
首先,安装NodeSource PPA以访问其内容。 确保您位于主目录中,并使用curl
检索Node.js 8.x存档的安装脚本:
cd ~
curl -sL https://deb.nodesource.com/setup_8.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,请键入:
nodejs -v
Outputv8.11.3
注意:从NodeSource PPA安装时,Node.js可执行文件称为nodejs
,而不是node
。
nodejs
包中包含nodejs
二进制文件以及npm
(Node模块的包管理器),因此您无需单独安装npm
。
npm
使用主目录中的配置文件来跟踪更新。 它将在您第一次运行npm
时创建。 执行此命令以验证是否已安装npm
并创建配置文件:
npm -v
Output5.6.0
为了使某些npm
包能够工作(例如,需要从源代码编译代码),您需要安装build-essential
包:
sudo apt install build-essential
您现在拥有必要的工具来处理需要从源代码编译代码的npm
包。
安装Node.js运行时后,让我们继续编写Node.js应用程序。
第2步 - 创建Node.js应用程序
让我们编写一个Hello World应用程序,它将“Hello World”返回给任何HTTP请求。 此示例应用程序将帮助您设置Node.js. 您可以将其替换为您自己的应用程序 - 只需确保修改您的应用程序以监听相应的IP地址和端口。
首先,让我们创建一个名为hello.js
的示例应用程序:
cd ~
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}/`);
});
保存文件并退出编辑器。
此Node.js应用程序监听指定的地址( localhost
)和端口( 3000
),并返回“Hello World!” 使用200
HTTP成功代码。 由于我们正在监听localhost ,因此远程客户端将无法连接到我们的应用程序。
要测试您的应用程序,请键入:
node hello.js
您将看到以下输出:
OutputServer running at http://localhost:3000/
注意:以这种方式运行Node.js应用程序将阻止其他命令,直到通过按CTRL+C
终止应用程序。
要测试应用程序,请在服务器上打开另一个终端会话,并使用curl
连接到localhost :
curl http://localhost:3000
如果您看到以下输出,则应用程序正常工作并监听正确的地址和端口:
OutputHello World!
如果没有看到预期的输出,请确保Node.js应用程序正在运行并配置为监听正确的地址和端口。
一旦你确定它正在工作,按CTRL+C
应用程序(如果你还没有)。
第3步 - 安装PM2
接下来让我们安装PM2,它是Node.js应用程序的进程管理器。 PM2可以对应用程序进行守护,以便它们作为服务在后台运行。
使用npm
在您的服务器上安装最新版本的PM2:
sudo npm install pm2@latest -g
-g
选项告诉npm
全局安装模块,以便它在系统范围内可用。
让我们首先使用hello.js
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.
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬───────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼───────┼──────────┤
│ hello │ 0 │ fork │ 1338 │ online │ 0 │ 0s │ 0% │ 23.0 MB │ sammy │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴───────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
如您所见,PM2自动分配App name
(基于文件名,不带.js
扩展名)和PM2 id
。 PM2还维护其他信息,例如进程的PID
,其当前状态和内存使用情况。
如果应用程序崩溃或被杀死,则在PM2下运行的应用程序将自动重新启动,但我们可以采取额外步骤,使用startup
子命令在系统启动时启动应用程序。 此子命令生成并配置启动脚本,以在服务器启动时启动PM2及其托管进程:
pm2 startup systemd
结果输出的最后一行将包含一个以超级用户权限运行的命令,以便将PM2设置为在引导时启动:
Output[PM2] Init System found: systemd
[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
systemd单元的状态:
systemctl status pm2-sammy
有关systemd的详细概述,请参阅Systemd Essentials:使用服务,单位和日记 。
除了我们所介绍的内容之外,PM2还提供了许多子命令,允许您管理或查找有关应用程序的信息。
使用此命令停止应用程序(指定PM2 App name
或id
):
pm2 stop app_name_or_id
重启应用程序:
pm2 restart app_name_or_id
列出PM2当前管理的应用程序:
pm2 list
使用其App name
获取有关特定应用程序的信息:
pm2 info app_name
可以使用monit
子命令提取PM2进程监视器。 这将显示应用程序状态,CPU和内存使用情况:
pm2 monit
请注意,运行不带任何参数的pm2
也会显示一个包含示例用法的帮助页面。
既然您的Node.js应用程序正在由PM2运行和管理,那么让我们设置反向代理。
第4步 - 将Nginx设置为反向代理服务器
您的应用程序正在运行并正在监听localhost ,但您需要为用户设置一种访问它的方法。 为此,我们将Nginx Web服务器设置为反向代理。
在先决条件教程中,您可以在/etc/nginx/sites-available/ example.com
文件中设置Nginx配置。 打开此文件进行编辑:
sudo nano /etc/nginx/sites-available/example.com
在server
块中,您应该有一个现有的location /
块。 使用以下配置替换该块的内容。 如果您的应用程序设置为监听其他端口,请将突出显示的部分更新为正确的端口号:
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
上可用,通过Web浏览器访问https:// example.com /
会将请求发送到hello.js
,在localhost上监听端口3000
。
您可以将其他location
块添加到同一服务器块,以提供对同一服务器上其他应用程序的访问。 例如,如果您还在端口3001
上运行另一个Node.js应用程序,则可以添加此位置块以允许通过http:// example.com / 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地址或域名)来尝试。
结论
恭喜! 现在,您的Node.js应用程序在Ubuntu 18.04服务器上的Nginx反向代理后面运行。 此反向代理设置足够灵活,可让您的用户访问您要共享的其他应用程序或静态Web内容。