美文网首页全栈工程师
阿里云ECS服务器部署Node.js项目全过程详解

阿里云ECS服务器部署Node.js项目全过程详解

作者: kovli | 来源:发表于2018-09-21 16:29 被阅读2336次

    本文详细介绍如何部署NodeJS项目到阿里云ECS上,以及本人在部署过程中所遇到的问题、坑点和解决办法,可以说是全网最全最详细的教程了。同时讲解了如何申请阿里云免费SSL证书,以及一台ECS服务器配置多网站的Nginx配置方法等。

    原文链接:http://www.kovli.com/2017/09/19/ecs-deploy/
    作者:Kovli

    1. 云服务器选择

    阿里云ECS是阿里巴巴旗下,目前国内最成熟稳定的云服务器提供商

    本文基于阿里云ECS云服务器讲解,目前有个人版,企业版,学生版可以选择。

    个人版 2折优惠活动,一年293元起,平均下来一个月20多即可拥有属于自己的服务器了。

    学生版 一个月9.5,24岁以下自动获得学生身份,学生推荐这个服务器。

    企业版 性能强大,有2-5折的活动。

    优惠券 阿里云产品通用代金券。

    这里以个人版 为例,流程都一样的。

    选购好云服务器,初学者1核1G就足够了,也就是默认的第一个入门级配置。

    操作系统选择CentOS系统

    image

    点击立即购买按钮,进入确认订单页面,这里选择自定义密码,设置ssh登录密码,后面要用,请牢记此密码

    image

    购买好以后,进入控制台,左侧功能栏选择云服务器ECS

    image

    点击箭头所指位置,即可获取服务器的公网地址,如图

    image

    记住公网IP,下一步要用到。

    2. 登陆服务器

    打开 Terminal,

    输入 ssh root@公网IP

    输入之前自己设的服务器登录密码(如果忘了,可以去上图右侧的管理-更多-重置密码)

    即可登陆服务器。

    首次登陆可能会询问公钥,yes 即可。

    关于 ssh 登陆,想要详细了解的可以看阮一峰写的这篇ssh原理与应用

    上述操作是使用 root 用户身份登陆,会直接进入到下图 红色箭头标出的 root 目录下。

    cd .. 跳转到上一层, 再 ls -a ,就可以看到类似下图的目录结构了。

    image

    图片引用自《鸟哥的Linux》

    3. 安装Nginx

    1. 在配置 nginx 时,可能会依赖于 PCRE 包和 zlib 包,先进行安装:

    cd /usr/local 切换目录

    cd /usr/local
    yum -y install pcre pcre-devel
    yum install -y zlib-devel
    

    2. 下载 nginx,这里nginx版本号可以根据需要选择,我选择1.13.3是当时最新的版本了,下面的node版本、mongodb版本都可以根据自己的需要选择

    nginx官网版本列表

    cd /usr/local/src 
    wget http://nginx.org/download/nginx-1.13.3.tar.gz
    

    3. 解压缩

    tar -xvzf nginx-1.13.3.tar.gz
    

    4. 配置nginx

    下载解压openssl

    wget https://www.openssl.org/source/openssl-1.0.2l.tar.gz
    
    tar -xvzf openssl-1.0.2l.tar.gz 
    
    

    cd 进入nginx解压包里,执行之前安装的pcre-devel与openssl-devel解决依赖问题

    cd nginx-1.13.3
    yum -y install pcre-devel openssl openssl-devel
    
    

    再执行配置脚本来进行编译预处理

    ./configure --prefix=/usr/local/nginx --conf-path=/usr/local/nginx/nginx.conf --with-http_stub_status_module --with-http_gzip_static_module --with-http_ssl_module --with-openssl=/usr/local/src/openssl-1.0.2l
    
    

    成功后显示如下信息,

    Configuration summary
      + using system PCRE library
      + using OpenSSL library: /usr/local/src/openssl-1.0.2l
      + using system zlib library
    
      nginx path prefix: "/usr/local/nginx"
      nginx binary file: "/usr/local/nginx/sbin/nginx"
      nginx modules path: "/usr/local/nginx/modules"
      nginx configuration prefix: "/usr/local/nginx"
      nginx configuration file: "/usr/local/nginx/nginx.conf"
      nginx pid file: "/usr/local/nginx/logs/nginx.pid"
      nginx error log file: "/usr/local/nginx/logs/error.log"
      nginx http access log file: "/usr/local/nginx/logs/access.log"
      nginx http client request body temporary files: "client_body_temp"
      nginx http proxy temporary files: "proxy_temp"
      nginx http fastcgi temporary files: "fastcgi_temp"
      nginx http uwsgi temporary files: "uwsgi_temp"
      nginx http scgi temporary files: "scgi_temp"
    

    make

    make && make install
    

    5. 使用 openssl 生成证书(以下介绍的是自己生成的供学习用,正常面向市场的产品请用认证的)

    openssl req -new -x509 -nodes -out server.crt -keyout server.key
    

    移动证书到nginx文件夹

    mv server.crt /usr/local/nginx
    mv server.key /usr/local/nginx
    

    认证的SSL证书,申请阿里云免费ssl证书:

    如何申请免费SSL证书 - 阿里云云盾证书

    操作技巧:想看到免费的证书,品牌选择Symantec,证书类型选择免费型DV SSL

    6. 修改 nginx 配置文件:

    vi /usr/local/nginx/nginx.conf
    
    

    修改如下

    
    #user  nobody;
    worker_processes  1;
    
    #error_log  logs/error.log;
    #error_log  logs/error.log  notice;
    #error_log  logs/error.log  info;
    
    #pid        logs/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        # 关闭错误页面的nginx版本数字,提高安全性
        server_tokens off;
    
        include       mime.types;
        default_type  application/octet-stream;
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        #keepalive_timeout  0;
        keepalive_timeout  65;
    
        #gzip  on;
    
        include /usr/local/nginx/sites-enabled-server/*;
    
    
    }
    
    

    新建文件夹用于存放多网站的nginx配置文件

    cd /usr/local/nginx/
    mkdir sites-enabled-server
    

    sites-enabled-server里面新增若干文件,以便这个ECS可以给多网站使用

    vim default

    
    server {
            listen 80;
            server_name _;
    
            return 404;
    }
    
    server {
            listen       80;
            server_name  你的域名.com www.你的域名.com;
    
            #charset koi8-r;
    
            #access_log  logs/host.access.log  main;
    
            location / {
                proxy_pass http://127.0.0.1:nodejs配置的端口号;
            }
    
            #error_page  404              /404.html;
    
            # redirect server error pages to the static page /50x.html
            #
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
    
            # proxy the PHP scripts to Apache listening on 127.0.0.1:80
            #
            #location ~ \.php$ {
            #    proxy_pass   http://127.0.0.1;
            #}
    
            # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
            #
            #location ~ \.php$ {
            #    root           html;
            #    fastcgi_pass   127.0.0.1:9000;
            #    fastcgi_index  index.php;
            #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            #    include        fastcgi_params;
            #}
            # deny access to .htaccess files, if Apache's document root
            # concurs with nginx's one
            #
            #location ~ /\.ht {
            #    deny  all;
            #}
        }
    
        # another virtual host using mix of IP-, name-, and port-based configuration
        #
        #server {
        #    listen       8000;
        #    listen       somename:8080;
        #    server_name  somename  alias  another.alias;
    
        #    location / {
        #        root   html;
        #        index  index.html index.htm;
        #    }
        #}
    
    

    vim default-ssl

    server {
            listen       443 ssl;
            server_name  localhost;
    
            ssl_certificate      server.crt;
            ssl_certificate_key  server.key;
    
            ssl_session_cache    shared:SSL:1m;
            ssl_session_timeout  5m;
    
            ssl_ciphers  HIGH:!aNULL:!MD5;
            ssl_prefer_server_ciphers  on;
    
            location / {
                 proxy_pass http://127.0.0.1:nodejs配置的端口号;
            }
        }
    ~       
    

    继续新增网站,例如,vim mywebsite.cn

    server {
            listen       80;
            server_name  mywebsite.cn www.mywebsite.cn;
    
            #charset koi8-r;
    
            #access_log  logs/host.access.log  main;
    
            location / {
                proxy_pass http://127.0.0.1:nodejs配置的mywebsite的端口号;
            }
    
            #error_page  404              /404.html;
    
            # redirect server error pages to the static page /50x.html
            #
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
    
            # proxy the PHP scripts to Apache listening on 127.0.0.1:80
            #
            #location ~ \.php$ {
            #    proxy_pass   http://127.0.0.1;
            #}
    
            # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
            #
            #location ~ \.php$ {
            #    root           html;
            #    fastcgi_pass   127.0.0.1:9000;
            #    fastcgi_index  index.php;
            #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            #    include        fastcgi_params;
            #}
    
            # deny access to .htaccess files, if Apache's document root
            # concurs with nginx's one
            #
            #location ~ /\.ht {
            #    deny  all;
            #}
        }
    

    7. 启动nginx

    /usr/local/nginx/sbin/nginx
    

    4. 安装 node

    • node -- 编译后二进制文件应在/usr/local/bin/node 下

    • mongodb -- 安装在/usr/local/mongodb 下

    下面就一步一步来

    1. 首先升级CentOS
    yum -y update

    2. 升级后,跳转到 /usr/local/src , 这个文件夹通常用来存放软件源代码

    cd /usr/local/src

    3. 下载 nodejs 代码,也可以使用scp命令直接上传,因为下载实在太慢了。

    wget http://nodejs.org/dist/node-latest.tar.gz(下载最新)
    wget http://nodejs.org/dist/v7.10.0/node-v7.10.0.tar.gz(推荐,稳定版本)
    
    

    4. 解压
    tar -xzvf node-v0.12.5.tar.gz

    5. 进入解压后的文件夹
    cd node-v0.12.5

    6. 执行配置脚本来进行编译预处理
    ./configure

    7. 安装v8可能有警告, //需要安装gcc

    8. sudo yum install gcc-c++ //安装gcc

    9. 编译源代码及安装

    当编译完成后,需要使之在系统范围内可用, 编译后的二进制文件将被放置到系统路径,默认情况下,Node二进制文件应该放在/user/local/bin/node文件夹下

    make && make install
    

    10. 安装pm2,建议 global 安装
    npm install pm2 -g

    11. 建立超级链接, 不然 sudo node 时会报 "command not found"

    • sudo ln -s /usr/local/bin/node /usr/bin/node
    • sudo ln -s /usr/local/lib/node /usr/lib/node
    • sudo ln -s /usr/local/bin/npm /usr/bin/npm
    • sudo ln -s /usr/local/bin/node-waf /usr/bin/node-waf
    • sudo ln -s /usr/local/bin/pm2 /usr/bin/pm2

    Nodejs到这里就基本安装完成了。

    5. 安装mongodb

    • 软件安装位置:/usr/local/mongodb

    • 数据存放位置:/var/mongodb/data

    • 日志存放位置:/var/mongodb/logs

    1. 首先下载安装包

    MongoDB下载中心

    cd /usr/local
    wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.6.tgz
    
    

    2. 解压安装包,重命名文件夹为mongodb

    tar zxvf mongodb-linux-x86_64-2.6.0.tgz
    mv mongodb-linux-x86_64-2.6.0 mongodb
    

    3. 创建数据和日志存放目录

    mkdir /var/mongodb
    mkdir /var/mongodb/data
    mkdir /var/mongodb/logs
    

    4. 打开rc.local文件,添加CentOS开机启动项:

    vim /etc/rc.d/rc.local
    

    5. 将mongodb启动命令追加到本文件中,让mongodb开机自启动:

    /usr/local/mongodb/bin/mongod --dbpath=/var/mongodb/data --logpath /var/mongodb/logs/log.log --logappend --auth --port 27017 --fork
    
    

    6. mongo权限设置

    sudo vi /etc/mongod.conf

    较新版本的增加安全校验的方法是配置文件最后面加上(网上很多旧版写法都是无效的)

    security: authorization: enabled

    如下所示:

    systemLog:
     destination: file
     path: /var/mongodb/logs/log.log
     logAppend: true
    storage:
     dbPath: /var/mongodb/data
    net:
     bindIp: 127.0.0.1
    security:
     authorization: enabled
    

    然后重启mongodb即可,这里说明下,初学也可以不设这个选项,这样操作数据库就不需要用户名密码了,从安全的角度看还是设了比较好,后面都是以设了安全校验来讲解。

    7. 关闭 vim 后,直接手动启动mongodb

    /usr/local/mongodb/bin/mongod --dbpath=/var/mongodb/data --logpath /var/mongodb/logs/log.log --logappend --auth --port 27017 --fork
    
    

    8. 启动mongo shell

    cd /usr/local/mongodb/bin/
    ./mongo
    

    9. 在 mongo shell 中创建超级管理员以及相关数据库到管理员及数据库

    use admin //admin database
    db.createUser({
     user: "myAdmin",
     pwd: "******",
     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
     }
     )
    

    10. 使用特权进入

    ./mongo -u "mydmin" -p "******" --authenticationDatabase "admin"
    

    11. 创建新数据库,并设置管理员

    > use mywebsite
    switched to db mywebsite
    > db.createUser(
    ... {
    ... user: "mywebsiteAdmin",
    ... pwd: "******",
    ... roles: [ { role: "readWrite", db: "mywebsite" }]
    ... }
    ... )
    
    > use secondwebsite
    switched to db secondwebsite
    > db.createUser(
    ... {
    ... user: "secondwebsiteAdmin",
    ... pwd: "******",
    ... roles: [ { role: "readWrite", db: "secondwebsite" }]
    ... }
    ... )
    

    以后进入其中的数据库需要权限,如果用超级管理员则不需要

    db.auth("mywebsiteAdmin", "******")
    

    12. mongodb数据迁移(用于从指定地址数据库迁移到云服务器上)

    //存放到某个目录
    ./mongodump -h 127.0.0.1:27017 -d mywebsite -o /home/mywebsite -u "mywebsiteAdmin" -p "******"
    
    //取出
    ./mongorestore  -h 127.0.0.1:27017 -d mywebsite /home/mywebsite/mywebsite -u "mywebsiteAdmin" -p "******"
    
    

    13. mongodb连接需要安全校验的配置
    以app.js为例,

    设置数据库连接
    vim app.js

    数据库连接类似下面的格式,由于数据库安装在同一服务器,因此 host 为127.0.0.1:

    var dbUrl = 'mongodb://用户名:登陆密码@127.0.0.1/databaseFoo';
    mongoose.connect(dbUrl)
    
    

    例如我的app.js里的这一段代码

    // 配置数据库
    mongoose.Promise = global.Promise;
    let mongoConnectUrl = 'mongodb://' + config.database.USERNAME + ':' + config.database.PASSWORD + '@' + config.database.HOST;
    mongoose.connect(mongoConnectUrl);
    

    到这里 mongodb 基本已经安装设置完成了。

    6. 上传NodeJS代码到服务器上

    把nodejs的程序放在 /home

    cd /home

    我使用码云管理代码。它的私有库是免费的。基本操作和 github 一样。

    1. 注意公钥的生成与添加

    ssh-keygen -t rsa -C "mywebsite@gmail.com"
    
    

    查看与复制公钥

    cat ~/.ssh/id_rsa.pub
    

    2. git安装

    yum install git
    

    3. 复制代码:
    git clone https://git.oschina.net/xxxxxxx/nodeapp.git //你的repo地址

    4. 进入 nodeapp 文件夹
    cd nodeapp
    (若后续代码变更,提交到 git repo 后直接git pull即可部署代码)

    5. 安装nodeapp的所有依赖

    npm install

    注意,使用淘宝镜像避免未知问题

    npm --registry https://registry.npm.taobao.org install
    
    

    7. 启动Node服务

    这里根据你nodejs所使用的框架不同而不同,

    例如koa2可以在package.jsonscripts里设置,参考阮一峰的npm scripts 使用指南

    thinkjs或者egg都有自己的启动方式,就不一一叙述了

    这里要注意的是,如果直接 npm startnode app.js 启动,则一旦退出 ssh 远程登陆,服务就会停止运行。

    使用pm2就可以解决这个问题,如果跟着教程走,你已经全局安装了pm2了,可以直接使用

    8. 其他说明

    这篇文章是汇聚了网上诸多教程及本人从零开始部署遇到的各种问题和坑点的解决方案所形成的一篇详细教程,由于涉及点比较多,加上版本更新迭代,如果在部署过程中遇到问题,可以在下面评论提问(需要登录Github账号才可以评论),或者给我发邮件(admin@kovli.com)。

    本文所述的本地操作系统:MacOS系统,阿里云ECS操作系统:CentOS 7.3,本地如果是Windows环境终端操作可能有所不同。

    Nginx的一些常用操作方法:

    /usr/local/nginx/sbin/nginx # 启动
    /usr/local/nginx/sbin/nginx -t #检查配置文件编写是否正确
    /usr/local/nginx/sbin/nginx -s reload #Nginx平滑重启 (一般用这个就可以了)
    /usr/local/nginx/nginx.conf #配置文件。
    

    文中已引用了部分参考文章,同时感谢下面的参考文章的作者:
    http://www.jianshu.com/p/0496ef49b2a5
    http://itbilu.com/other/relate/NJ2TJohl.html
    https://segmentfault.com/a/1190000004051670
    http://borninsummer.com/2015/06/17/notes-on-developing-nodejs-webapp/
    https://bbs.aliyun.com/read/146189.html
    https://segmentfault.com/q/1010000003937372


    版权声明:
    转载时请注明作者Kovli以及本文地址:
    http://www.kovli.com/2017/09/19/ecs-deploy/


    相关文章

      网友评论

        本文标题:阿里云ECS服务器部署Node.js项目全过程详解

        本文链接:https://www.haomeiwen.com/subject/dtqznftx.html