如何在Ubuntu 16.04上设置生产型Node.js应用

本教程指导如何在Ubuntu16.04服务器上设置Node.js应用,利用PM2进程管理器和Nginx反向代理实现稳定运行及HTTPS安全访问。

提供:ZStack云计算

内容介绍

Node.js是一套开源JavaScript运行时环境,能够轻松构建服务器端与网络应用。这套平台可运行在Linux、OS X、FreeBSD以及Windows系统之上。Node.js应用可通过命令行运行,但今天我们着重关注以服务方式运行,因此其需要在重启或崩溃情况下自动恢复,并可安全应用于生产环境。

在本教程中,我们将探讨如何在单一Ubuntu 16.04服务器上设置能够用于实际生产的Node.js环境。此服务器将运行由PM2负责管理的Node.js应用,且为用户提供经由Nginx反向代理实现的安全访问。Nginx服务器将提供HTTPS,并由Let’s Encrypt提供免费证书。

先决条件

本教程要求大家拥有一套Ubuntu 16.04服务器,且配置一个拥有sudo权限的非root用户,具体方法参阅Ubuntu 16.04服务器初始设置指南

另外,大家还需要拥有自己的域名,且指向服务器的公共IP地址。

下面在服务器上安装Node.js运行时。

安装Node.js

我们将使用NodeSource软件包归档文件安装最新Node.js版本。

首先,大家需要安装NodeSource PPA以访问其内容。现在前往主目录,使用curl以提取Node.js 6.x归档文件中的安装脚本:

- cd ~

- curl -sL https://deb.nodesource.com/setup_6.x -o nodesource_setup.sh

大家可以使用nano(或者其它文本编辑器)修改此脚本内容:

- nano nodesource_setup.sh

下面使用sudo权限运行此脚本:

- sudo bash nodesource_setup.sh

此PPA将被添加至配置当中,而本地软件包缓存也将自动更新。在从nodesource运行了设置脚本后,大家即可以同样的方式安装Node.js软件包:

- sudo apt-get install nodejs

除了nodejs二进制代码外,nodejs软件包还包含npm,意味着大家无需单独安装npm。不过为了确保某些npm软件包能够正常运行(例如需要对源代码进行编译的情况),大家需要安装build-essential软件包:

- sudo apt-get install build-essential

Node.js运行时已经安装完成,下面开始编写我们的Node.js应用。

请注意:当从NodeSource PPA进行安装时,Node.js可执行文件名为nodejs,而非node。

创建Node.js应用

我们这里编写一个简单的Hello World应用,即向任意HTTP请求返回“Hello World”。

Hello World代码

首先,创建并打开Node.js应用以进行编辑。在本示例中,我们将使用nano对hello.js示例应用进行编辑:

- cd ~

- nano hello.js

在文件中插入以下代码。如果大家愿意,也可以替换其中的8080端口(请确保使用非admin端口,例如1024或更高):

hello.js

#!/usr/bin/env nodejs
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8080, 'localhost');
console.log('Server running at http://localhost:8080/');

保存并退出。

此Node.js应用能够监听特定地址(localhost)与端口(8080),并利用200 HTTP success代码返回“Hello Wor”字样。由于我们监听的是localhost,因此远程客户端无法接入我们的应用。

测试应用

为了进行应用测试,我们将hello.js设为可执行:

- chmod +x ./hello.js

运行方法如下:

- ./hello.js

Output

Server running at http://localhost:8080/

请注意:以这种方式运行Node.js应用会阻断其它命令,直到以Ctrl-C关闭该应用。

为了测试此应用,我们需要在服务器上打开另一终端会话并利用curl接入localhost:

- curl http://localhost:8080

如果大家看到以下输出结果,则该应用已经正常运行并开始监听正确的地址与端口:

Output

Hello World

如果大家看到的输出结果有误,请确保Node.js应用正在运行并监听正确的地址与端口。

测试完成后,按下Ctrl-C关闭应用。

安装PM2

现在安装PM2,这是一款面向Node.js应用的进程管理器。PM2能够轻松管理应用并实现后台化(以服务形式将其运行于后台)。

我们将使用npm安装各Node模块。下面安装PM2:

- sudo npm install -g pm2

其中的-g要求npm将模块安装在本地,从而实现系统内使用。

利用PM2管理应用

易于上手及使用,下面来了解PM2的几种基本用法。

启动应用

首先利用pm2命令在后台运行hello.js应用:

- pm2 start hello.js

这条命令还能够将应用添加至PM2进程列表中,其会在每次应用启动时输出结果:

Output

[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
[PM2] Starting hello.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name │ id │ mode │ pid  │ status │ restart │ uptime │ memory      │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ hello    │ 0  │ fork │ 3524 │ online │ 0       │ 0s     │ 21.566 MB   │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app

如大家所见,PM2能够自动分配一个App名称(基于文件名称,但不包含.js后缀)以及一个PM2 ID。PM2还能够包含其它信息,例如进程的PID、当前状态以及内存使用量。

运行在PM2下的应用可在崩溃或被关闭后自动恢复,但我们还需要另行调整以确保其在系统重启后也能得到恢复。幸运的是,PM2能够非常简单的实现方式,即startup子命令。

这里的startup子命令能够生成并配置一套startup脚本,用于启动PM2并在服务器启动时管理进程。大家还需要指定其运行平台,即ubuntu:

- pm2 startup systemd

输出结果的最后一行中包含一条必须以superuser权限运行的命令:

Output

[PM2] You have to run this command as root. Execute the following command:
  sudo su -c "env PATH=$PATH:/usr/bin pm2 startup systemd -u sammy --hp /home/sammy"

运行该命令用于(类似于以上内容,但sammy应被替换为实际用户名)设置PM2以确保其在引导过程中启动:

- sudo su -c "env PATH=$PATH:/usr/bin pm2 startup systemd -u sammy --hp /home/sammy"

这条命令将创建一个systemd单元以确保在引导时运行pm2。该pm2实例运行hello.js。大家可以利用systemctl命令检查该systemd单元的状态:

- systemctl status pm2

关于更多细节信息,请参阅Systemd基础:Service、Unit与Journal一文。

其它PM2使用方式(可选)

PM2提供多种子命令,允许大家管理应用并查看相关信息。请注意,直接运行pm2而不加任何参数则会显示帮助页面,其中包括示例使用情况等。

使用以下命令关闭应用(指定PM2应用名称或ID):

- pm2 stop app_name_or_id

以下命令可重启应用:

- pm2 restart app_name_or_id

以下list子命令可列出当前由PM2管理的各应用:

- pm2 list

大家可以利用info子命令查看更多特定应用的相关信息:

- pm2 info example

PM2进程监控器则需要使用monit子命令,其能够显示应用状态、CPU与内存占用量:

- pm2 monit

现在Node.js应用已经开始运行并由PM2管理,接下来探讨反向代理。

设置Nginx作为反向代理服务器

现在我们的应用开始运行,监听localhost,接下来需要设置用户访问机制。我们将利用Nginx Web服务器作为反向代理。在本教程中,我们从零开始进行Nginx设置。如果大家已经拥有自己的Nginx服务器,则可将locationblock复制到选定的serverblock中(确保位置信息不会与现有内容相冲突)。

首先使用apt-get安装Nginx:

- sudo apt-get install nginx

现在打开默认server block配置文件进行编辑:

- sudo nano /etc/nginx/sites-available/default

删除文件内的全部内容并插入以下配置。注意将server_name替换为实际域名。另外,如果大家的应用需要监听其它端口,也记得进行对应调整:

/etc/nginx/sites-available/default

server {
listen 80;

server_name example.com;

location / {
    proxy_pass http://localhost:8080;
    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域名,则通过浏览器访问http://example.com/即会向hello.js发送请求,并监听localhost上的端口8080。

大家也可以添加其它location block以在同一服务器上访问其它应用。例如,如果我们在端口8081上运行有另一Node.js应用,则可添加以下location block以通过http://example.com/app2实现访问:

Nginx Configuration — Additional Locations

location /app2 {
    proxy_pass http://localhost:8081;
    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;
}

完成添加之后,保存并退出。

重启Nginx:

- sudo systemctl restart nginx

假定大家的Node.js应用正在运行,应用与Nginx配置也一切正常,则可通过Nginx反向代理实现应用访问。

下面利用Let’s Encrypt保护应用连接。

安装Let’s Encrypt及其关联性

Let’s Encrypt是一款新型证书发布程序,能够轻松帮助我们获取免费的TLS/SSL证书。

大家必须拥有或者控制需要使用证书的注册域名。如果大家还没有注册域名,则可通过各域名注册商进行申请。

另外,请记得为服务器的公共IP地址创建一条A记录,因为Let’s Encrypt会据此进行验证。

关于这部分工作的具体信息,请参阅如何利用DigitalOcean设置主机名称以及如何将通用域名分配给DigitalOcean命名服务器

在安装Let’s Encrypt前,确保git与bc软件包已经安装完成:

- sudo apt-get -y install git bc

接下来将letsencrypt库由GitHub克隆至/opt/letsencrypt。其中/opt/目录属于发行版官方软件包库不包含的各软件的标准保存位置:

- sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

将其克隆至letsencrypt目录:

- cd /opt/letsencrypt
获取初始证书

由于nginx目前已经运行在端口80上,而Let’s Encrypt客户端也需要使用该端口以验证域名,所以暂时停止nginx:

- sudo systemctl stop nginx

使用Standalone插件运行letsencrypt:

- ./letsencrypt-auto certonly --standalone

根据提示输入信息,包括邮箱地址、同意服务条款以及证书适用的域名。完成后,大家将获得以下信息:

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/your_domain_name/fullchain.pem. Your cert will expire
on 2016-08-10. To obtain a new version of the certificate in the
future, simply run Let's Encrypt again.
- If you like Let's Encrypt, please consider supporting our work by:

Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
Donating to EFF:                    https://eff.org/donate-le

请注意证书的路径与过期日期。大家的证书文件现在应该已经存在于/etc/letsencrypt/your_domain_name/位置了。

面向HTTPS配置Nginx

大家需要在Nginx配置中添加更多细节。在nano中打开/etc/nginx/sites-enabled/default:

- sudo nano /etc/nginx/sites-enabled/default

利用以下内容替换其原有内容:

/etc/nginx/sites-enabled/default

# HTTP - redirect all requests to HTTPS:
server {
    listen 80;
    listen [::]:80 default_server ipv6only=on;
    return 301 https://$host$request_uri;
}

# HTTPS - proxy requests on to local Node.js app:
server {
    listen 443;
    server_name your_domain_name;

    ssl on;
    # Use certificate and key provided by Let's Encrypt:
    ssl_certificate /etc/letsencrypt/live/your_domain_name/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain_name/privkey.pem;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

    # Pass requests for / to localhost:8080:
    location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-NginX-Proxy true;
            proxy_pass http://localhost:8080/;
            proxy_ssl_session_reuse off;
            proxy_set_header Host $http_host;
            proxy_cache_bypass $http_upgrade;
            proxy_redirect off;
    }
}

保存并退出。再次启动Nginx:

- sudo systemctl start nginx

现在大家可以在浏览器中访问http://your_domain_name/以测试证书及Nginx配置了。在这里,大家应当被重新定向至http://your_domain_name/,且在不触发任何安全错误的前提下查看到“Hello World”。

设置Let’s Encrypt自动续租

注意:即使不进行证书续租,大家也可以顺利完成本教程。不过在长期运行的生产环境下,自动续租显然非常必要。

Let’s Encrypt证书的有效期为90天,这是为了尽可能缩短问题证书的存在时间。

Let’s Encrypt客户端能够自动进行证书续租,但大家仍然需要重复证书获取流程,或者使用脚本来完成这项任务。这里建议大家参阅如何在Ubuntu 16.04上利用Let’s Encrypt保护Nginx,特别是其中的设置自动续租部分。

总结

恭喜大家!现在各位已经拥有了运行在Ubuntu 16.04服务器上且由Nginx反向代理支持的Node.js应用。这套反向代理设置非常灵活,足以将用户引导至其它应用或者静态页面处。

本文来源自DigitalOcean Community。英文原文:How To Set Up a Node.js Application for Production on Ubuntu 16.04 By Brennen Bearnes

翻译:diradw

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值