如何建立一个应用程序的Node.js生产在Ubuntu 16.04

介绍

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服务器,与非root用户配置的sudo特权,如中所述的Ubuntu 16.04服务器初始设置指南

它还假定您有一个域名,指向服务器的公共IP地址。

让我们开始在你的服务器上安装Node.js运行时。

安装Node.js

我们将安装Node.js的最新当前版本中,使用NodeSource包文件。

首先,您需要安装NodeSource PPA才能访问其内容。 确保你在你的home目录里,并用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应用程序,它只是返回的“Hello World”的任何HTTP请求。 这是一个示例应用程序,将帮助您获得您的Node.js设置,您可以替换为您自己的应用程序 - 只是确保您修改您的应用程序以监听相应的IP地址和端口。

Hello World代码

首先,创建并打开您的Node.js应用程序以进行编辑。 在本教程中,我们将使用nano编辑示例应用程序调用hello.js

cd ~
nano hello.js

将以下代码插入到文件中。 如果你愿意,你可以更换高亮度显示端口, 8080 ,在这两个位置(一定要使用非管理端口,即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 ),和一个返回“Hello World”的200 HTTP成功代码。 由于我们监听localhost,远程客户端将无法连接到我们的应用程序。

测试应用程序

为了测试你的应用程序,标志hello.js可执行文件:

chmod +x ./hello.js

并运行它像这样:

./hello.js
OutputServer running at http://localhost:8080/

注:以这种方式运行的Node.js应用程序会阻止其他命令,直到应用程序按Ctrl-C杀害。

为了测试应用程序,您的服务器上打开另一个终端会话,并与连接到本地主机 curl

curl http://localhost:8080

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

OutputHello World

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

一旦你确定它的工作,杀死应用程序(如果您还没有),按Ctrl + C。

安装PM2

现在我们将安装PM2,它是Node.js应用程序的进程管理器。 PM2提供了一种简单的方法来管理和守护应用程序(在后台作为服务运行它们)。

我们将使用npm ,用于节点模块的软件包管理器,与Node.js的安装,到我们的服务器上安装PM2。 使用此命令安装PM2:

sudo npm install -g pm2

-g选项告诉npm全球范围内安装模块,所以它的系统范围内可用。

使用PM2管理应用程序

PM2简单易用。 我们将介绍PM2的几个基本用途。

启动应用程序

你会想要做的第一件事就是使用pm2 start命令来运行你的应用程序, 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自动分配一个应用程序名称 (基于文件名,没有.js扩展名)和PM2 ID。 PM2还维护的其它信息,如进程的PID,其当前状态,和存储器使用率。

在PM2下运行的应用程序将在应用程序崩溃或被终止时自动重新启动,但需要执行额外的步骤才能在系统启动(启动或重新引导)时启动应用程序。 幸运的是,PM2提供了一种简单的方法来做到这一点, startup子命令。

startup子产生并配置启动脚本启动PM2和管理流程上的服务器引导。 你还必须指定要运行的平台,这是ubuntu ,在我们的例子:

pm2 startup systemd

结果输出的最后一行将包含一个必须使用超级用户权限运行的命令:

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 您可以检查与systemd单元的状态systemctl

systemctl status pm2

对于systemd的详细介绍,请参见Systemd要领:用服务,单位和学报工作

其他PM2用法(可选)

PM2提供了许多子命令,允许您管理或查找有关应用程序的信息。 请注意,运行pm2不带任何参数将显示一个帮助页面,包括用法示例,涵盖PM2使用在除本节中的更多细节。

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

pm2 stop app_name_or_id

重新启动使用此命令(指定PM2的应用程序App nameid ):

pm2 restart app_name_or_id

目前由PM2管理的应用程序列表也可以抬头与list子命令:

pm2 list

有关特定应用程序的更多信息,可以通过使用发现info子(指定PM2 应用程序名称ID):

pm2 info example

该PM2进程监视器可以与拉升monit子命令。 这将显示应用程序状态,CPU和内存使用情况:

pm2 monit

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

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

现在,您的应用程序正在运行,并监听本地主机 ,你需要设置为你的用户访问它的方法。 我们将为此设置一个Nginx Web服务器作为反向代理。 本教程将从头开始设置一个Nginx服务器。 如果你已经有一个Nginx的服务器设置,您可以将刚才复制location块到您选择的服务器模块(确保位置不与任何Web服务器的现有内容的冲突)。

首先,使用apt-get安装Nginx:

sudo apt-get install nginx

现在打开默认服务器块配置文件进行编辑:

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

删除文件中的所有内容并插入以下配置。 一定要代替你自己的域名为server_name指令。 此外,更改端口( 8080 ),如果你的应用程序设置为监听在不同的端口:

/ 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/通过Web浏览器将请求发送到hello.js ,侦听端口8080本地主机

您可以添加其他location的块到同一服务器模块能提供访问其他应用程序在同一台服务器上。 例如,如果您还运行在端口另一个应用程序的Node.js 8081 ,您可以通过添加此位置区块允许访问它http://example.com/app2

Nginx配置 - 其他位置
    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;
    }

为应用程序完成添加位置块后,保存并退出。

确保您没有通过键入以下语法错误:

sudo nginx -t

接下来,重启Nginx:

sudo systemctl restart nginx

接下来,允许通过防火墙到Nginx的流量,如果你启用:

sudo ufw allow 'Nginx Full'

假设你的Node.js应用程序正在运行,你的应用程序和Nginx配置是正确的,你现在应该能够通过Nginx反向代理访问你的应用程序。 尝试通过访问您的服务器的URL(其公共IP地址或域名)。

现在您可以访问您的应用程序,我们将使用Let's Encrypt通过HTTPS保护您的应用程序的连接。

安装让我们加密和依赖

Let's Encrypt是一个新的证书颁发机构,提供了一种获取免费TLS / SSL证书的简单方法。

您必须拥有或控制您希望使用证书的注册域名。 如果您还没有注册域名,您可以向其中一个域名注册商(例如Namecheap,GoDaddy等)注册一个域名。

如果你还没有准备好,一定要创建一条A记录指向你自己的域名服务器的公网IP地址。 这是必需的,因为Let's Encrypt验证您拥有它为其颁发证书的域。 例如,如果你想获得一个证书example.com ,该域必须解析到服务器的验证过程工作。

有关此过程的详细信息,请参阅如何设置主机名与DigitalOcean怎么点从常见的域名注册商DigitalOcean域名服务器

虽然咱们加密项目已更名为他们的客户certbot ,包在Ubuntu 16.04版本库的名称就是letsencrypt 这个包将完全满足我们的需要。

要安装软件包,请键入:

sudo apt-get install letsencrypt

letsencrypt现在客户应准备好您的服务器上使用。

检索初始证书

由于nginx是已经在端口80上运行,并且让我们的加密客户端需要为了验证域名所有权的这个端口,停止nginx暂时:

sudo systemctl stop nginx

运行letsencrypt的独立插件:

sudo letsencrypt 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 /

为Nginx配置HTTPS

你需要添加一些细节到你的Nginx配置。 开放/etc/nginx/sites-enabled/defaultnano (或您选择的编辑器):

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;
        }
}

退出编辑器并保存文件。

键入以下内容以检查语法错误的配置:

sudo nginx -t

当没有检测到错误时,再次启动Nginx:

sudo systemctl start nginx

您可以通过访问测试新的证书和Nginx的配置http:// your_domain_name /在浏览器中。 您应该被重定向到https:// your_domain_name / ,没有任何安全错误,并看到的“Hello World”你的Node.js应用程序打印。

设置让我们加密自动续订

警告:您可以安全地完成本指南,而不必担心证书更新,但你需要解决它的任何长寿命的生产环境。

您可能已经注意到,您的Let's Encrypt证书将在90天后到期。 这是Let's Encrypt方法的一个故意功能,旨在最小化受损证书在出现问题时可以存在的时间。

Let's Encrypt客户端可以自动更新您的证书,但同时您将不得不手动重复证书检索过程,或使用预定的脚本为您处理它。 自动化这一过程的详细信息在如何使用让我们在Ubuntu 16.04加密安全Nginx的 ,特别是在部分设置自动续约

结论

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

赞(52) 打赏
未经允许不得转载:优客志 » 系统运维
分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏