从头配置NodeJs和PM2

下面我来分享下配置Centos7的吐血经历,(╯﹏╰)蓝瘦香菇…

环境介绍

本地: Mac OSX

远端服务器:腾讯云ECS(1核CPU、1GB内存),系统版本为CentOS 7.0

服务器用户:root (期待有人来攻击我的垃圾服务器)

Github:github.com/Barry215

安装目的

本地代码开发测试后,更新到Github仓库,然后通过PM2部署远程服务器,服务器再部署Node的应用,最后使用Nginx进行反向代理

远端安装Nodejs

我看网上大多都是通过下载压缩包来安装的,如果我没有在本地装过Node,也许我会去选择,但是因为在Mac上吃过这个坑(node版本更新太快,而且mac上用brew来安装据说有bug),所以还是打算先安装nvm,用nvm来安装Node。

更新yum

把yum更新到最新版本:

1
yum update -y  #y参数是让升级过程中都默认yes

我们将使用最新源代码构建Node.js,要进行软件的安装,需要一组用来编译源代码的开发工具:

1
yum -y groupinstall "Development Tools"

安装Nvm

用curl来安装nvm,但是这个命令有时效性,最新看https://github.com/creationix/nvm/

1
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash

在mac上这样就ok了,因为它会自动地在.bash_profile文件里写上

1
2
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm

但是亲身体验Centos发现要自己加上去,加完后记得source .bash_profile更新

当然不一定要写在.bash_profile上

官方说明(写在那四个文件上应该都有效,区别参考):

The script clones the nvm repository to ~/.nvm and adds the source line to your profile (~/.bash_profile, ~/.zshrc, ~/.profile, or ~/.bashrc).

然后,可以用一下 nvm --version 看一下安装好了没有

安装Node

因为nvm是从国外的官网获取资源,所以我们再加入淘宝团队的镜像

1
export NVM_NODEJS_ORG_MIRROR=https://npm.taobao.org/mirrors/node

这个也是放在.bash_profile里,加完后记得source .bash_profile更新

下面我就开始安装Node

1
nvm install stable  #或者nvm install v7.5.0,选一个自己适用的版本

执行命令 node -v 就可以看到现在使用的 Node.js 的版本号

执行命令 npm -v 就可以看到现在使用的 NPM 的版本号

安装cnpm

因为原版的 npm 在国内安装东西是很慢的,要解决慢就一定要用镜像

cnpm 就是使用了淘宝的 NPM 镜像的 npm

安装方法也很简单:

1
npm install -g cnpm --registry=https://registry.npm.taobao.org

只需要一步就可以安装好 cnpm

运行 cnpm -v 可以看到安装好了的 cnpm 的版本

如果不使用PM2的话,用scpsftp把代码传到服务器,可以直接运行NodeJs了

因为 Nodejs 是一个Web服务器,所以它本身就已经有自己的端口了,我设置的是3000

使用 node app.js 之类的手段可以让 Nodejs 服务器运行起来

远端安装PM2

本地和远端都使用命令安装

1
npm install pm2 -g

安装成功后使用pm2 -v参看版本

Github与服务器建立信任

如果之前github上已经放过服务器的key了,那就不用下面的操作了

如果没有,那就

1
2
ssh-keygen #生成公钥和密钥
vi ~/.ssh/id_rsa.pub #去复制公钥里的内容

然后在github上的setting里的SSH keys加入id_rsa.pub的内容就行了

本地创建项目

在github上创建一个新的项目,接着将本地项目与github远程仓库建立连接

1
2
git remote add origin https://github.com/Barry215/node_demo.git
git push -u origin master #第一次提交好像要用-u,之后就不用了

本地配置pm2

在本地的项目目录下,输入:

1
pm2 ecosystem

会生成一个ecosystem.config.js(版本原因,也可能是ecosystem.json)文件

因为目前我们仅部署一个应用,因此,先把不必要的信息删除,即删除apps部分的第二项

同时把我们的目标文件改为你应用的入口文件,此处修改为Express.js的默认设置,即:

1
script : "./bin/www",

apps部分就设置完毕了,然后再设置deploy部分。其中production用于生产环境,dev用于开发环境

我的配置结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
module.exports = {

apps : [
//由于我们此次只有一个项目,我们只配置一个app
{
name : "node_demo", //自己取一个名字
script : "./bin/www",
env: {
COMMON_VARIABLE: "true"
},
env_production : {
NODE_ENV: "production"
}
}
],

deploy : {
//生产环境部署配置
production : {
//登录远程服务器的用户名
user : "root",
//远程服务器的IP或hostname,此处可以是数组同步部署多个服务器
host : "115.159.190.30",
//远端名称及分支名
ref : "origin/master",
//git仓库地址
repo : "git@github.com:Barry215/node_demo.git",
//远程服务器部署目录,需要填写user具备写入权限的目录
path : "/home/root/www/production",
//部署后需要执行的命令
"post-deploy" : "npm install && pm2 startOrRestart ecosystem.config.js --env production"
}
//因为我没有开发环境的分支,所以dev部分就不写了
}
};

免密登录服务器

因为pm2的部署是通过ssh进行的,因此需要开通本地到远程服务器的无密码登录

具体步骤看我的另一篇文章—SSH免密登录服务器

配置pm2

在本地应用目录下,执行pm2 deploy命令

1
pm2 deploy ecosystem.config.js production setup

提示错误:

1
Invalid or unexpected token

仔细检查配置文件,看是否有写错,如果看不出可以放到vim里看

并且注意ecosystem.config.js版本的顶部会有module.exports =

ecosystem.json版本的顶部直接是{开始的

又提示错误:

1
2
3
4
5
Host key verification failed.
fatal: Could not read from remote repository.
Please make sure you have the correct access rights and the repository exists.
failed to clone
Deploy failed

此时主要是在远程服务器中,并未将http://github.com加入known_hosts,在服务器端通过如下命令设置:

1
ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts

在本地继续执行部署命令:

1
pm2 deploy ecosystem.config.js production setup

此时,如无其他问题,输出应提示:

1
2
  ○ setup complete
--> Success

至此,pm2的本地部署设置完毕。

pm2部署服务器

pm2部署要求本地的项目必须将修改提交到github

1
2
3
git add .
git commit -m "update ecosystem"
git push

提交后,在本地应用目录,输入如下命令进行生产环境的部署:

1
pm2 deploy ecosystem.config.js production

如果看到

1
2
3
4
Use `pm2 show <id|name>` to get more details about an app
○ hook test
○ successfully deployed origin/master
--> Success

说明部署成功

在远程服务器查看端口情况:

1
netstat -antp

可以看到应用默认部署的3000端口已经开放了。通过浏览器打开:

1
http://115.159.190.30:3000

可以看到部署的Web应用可以访问了。(如果netstat -antp中可见3000端口可访问,可以检查下ECS的防火墙设置,确保3000端口对外开放)

服务器设置pm2开机自启

开启启动设置,此处是CentOS系统,其他系统替换最后一个选项(可选项:ubuntu, centos, redhat, gentoo, systemd, darwin, amazon):

1
pm2 startup centos

然后按照提示需要输入的命令进行输入:

1
sudo su -c "env PATH=$PATH:/usr/bin pm2 startup centos -u root --hp /home/root"

保存pm2设置

1
pm2 save

现在重新启动系统,测试是否可以开机启动:

1
sudo reboot

等系统重启后,通过浏览器检查系统是否自动启动:

1
http://115.159.190.30:3000

如果启动正常,说明设置成功!

(可选)更新git

因为Centos 7 上的git版本是1.8,我嫌弃它,所以打算安装新的

卸载原有 git

1
yum remove git

安装依赖文件

1
2
yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel #最好都装
yum install gcc perl-ExtUtils-MakeMaker #一定要安装

切换到/usr/local/src目录下

下载最新版git

1
wget https://www.kernel.org/pub/software/scm/git/git-2.11.1.tar.gz

解压并进入解压后的目录

1
tar -zxvf git-2.11.1.tar.gz && cd git-2.11.1

编译安装

1
2
3
4
5
6
7
./configure #必须执行

#二选一
make && make install
或者(我试的好像是上面这种)
make prefix=/usr/local/git all
make prefix=/usr/local/git install

下面这种需要加环境,上面这种跳过

1
2
export PATH=$PATH:/usr/local/git/bin #把它放到.bash_profile里
source ~/.bash_profile

查看环境

1
echo $PATH

查看版本

1
git --version

安装Nginx

通过Nginx反向代理,可以让服务器上某端口,指向指定域名的80端口,这样访问就不需要加端口号了

安装依赖包

1
2
3
4
yum install -y gcc gcc-c++
yum -y install openssl
yum -y install zlib
yum -y install pcre

以上安装的是一些主要的依赖包,具体可根据自己情况或者报错信息提示安装或修改

我装了zlib zlib-devel pcre-devel

(可选)安装pcre依赖

我先前不知道可以yum安装,所以是wget装的

1
2
3
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.40.tar.gz 
./configure --prefix=/usr/local/pcre
make && make install

下载Nginx

网上说可以配置yum去安装它,但是我没有尝试

1
wget http://nginx.org/download/nginx-1.10.3.tar.gz

解压

1
tar -zxvf nginx-1.10.3.tar.gz

编译安装

1
2
3
cd nginx-1.10.3
./configure --prefix=/usr/local/nginx --with-pcre=../pcre-8.40
make && make install

启动Nginx

进入Nginx的安装目录下,直接启动Nginx

1
2
3
4
5
cd /usr/local/nginx/sbin
./nginx -h #查看帮助
./nginx -t #判断配置文件是否正确
./nginx #重启是 ./nginx -s reload
#也可以 killall -9 nginx 杀死进程再启动,也可以是kill -9 nginx

也可以使用脚本去启动,停止和重启Nginx—参考链接

配置Nginx

进入配置目录

1
cd /usr/local/nginx/conf

配置nginx.conf

1
vi nginx.conf

配置参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# user nobody;
worker_processes 1;
error_log /usr/local/nginx/logs/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
# include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
upstream my_nodejs_upstream {
server 127.0.0.1:3000;
keepalive 64;
}
server {
listen 80;
server_name www.maijinta.cn;//你的域名
# access_log /usr/local/nginx/logs/access.log;
# error_log /usr/local/nginx/logs/error.log;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_pass http://my_nodejs_upstream/;
}
}
}

重启Nginx

1
2
./nginx -t #判断配置文件是否正确
./nginx -s reload #重启Nginx

这样之后,就可以用80端口访问我们的NodeJs应用了

结束

往后就可以使用pm2来自动化部署Node.js了

1
pm2 deploy ecosystem.config.js production