学习Express之部署express-demo

一、服务器准备

    服务器ip地址为:172.16.70.174

    1.安装 Node.js

    参考:http://my.oschina.net/songzhu/blog/608129

    2.安装 PM2

    PM2 是一个带有负载均衡功能的 Node 应用的进程管理器。

    全局安装 PM2

$ npm install pm2 -g
$ pm2 list
[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
┌──────────┬────┬──────┬─────┬────────┬─────────┬────────┬────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ memory │ watching │
└──────────┴────┴──────┴─────┴────────┴─────────┴────────┴────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

    安装 PM2 如果出现错误,大概是网络和权限问题导致的。仔细看一下错误提示,如果是网络问题,那么多重试几次应该就可以了。

    3.准备发布目录    

    /home/admin/publish/web/express-demo

$ cd ~
$ mkdir publish && cd publish
$ mkdir web && cd web
$ mkdir express-demo && cd express-demo
$ pwd
/home/admin/publish/web/express-demo

二、创建 PM2  启动脚本

    进入 express-demo 目录,添加文件 pm2-start.json

$ touch pm2-start.json

    添加以下内容:

[
    {
        "name"        : "express-demo",
        "script"      : "./app.js",
        "watch"       : false,
        "instances"   : "4",
        "exec_mode"   : "cluster_mode",
        "env": {
            "NODE_ENV": "production"
        },
        "out_file": "./logs/app.log",
        "error_file": "./logs/err.log",
    }
]

    通过 pm2 start pm2-start.json,可启动 express-demo。

    更详细的配置:http://pm2.keymetrics.io/docs/usage/application-declaration/

三、创建 Gulp 任务

    Gulp 用自动化构建工具增强你的工作流程。

    1.全局安装 gulp

$ npm install gulp -g
$ gulp -v
[23:57:39] CLI version 3.9.0

    2.作为项目的开发依赖安装 gulp

$ npm install --save-dev gulp
$ gulp -v
[23:58:00] CLI version 3.9.0
[23:58:00] Local version 3.9.0

    3.在项目根目录创建 gulpfile.js

$ touch gulpfile.js
$ gulp
[23:57:01] Using gulpfile ~/demos/express-demo/gulpfile.js
[23:57:02] Task 'default' is not in your gulpfile
[23:57:02] Please check the documentation for proper gulpfile formatting

    看到错误是因为我没还没有在 gulpfile.js里面添加内容

    4.添加 gulp 部署依赖

$ npm install --save-dev gulp-util gulp-shell gulp-ssh gulp-zip through2 scp2 async progress

    gulp-util

    gulp-shell

    gulp-ssh

    gulp-zip

    through2

    scp2

    async

    progress

    5.在项目根目录创建 deploy-ssh.js

$ touch deploy-ssh.js

    添加以下内容:

var gulp = require('gulp');
var gutil = require('gulp-util');
var through = require('through2');
var ScpClient = require('scp2').Client;
var ssh = require('gulp-ssh');
var async = require('async');
var ProgressBar = require('progress');

const PLUGIN_NAME = 'deploy-ssh'

module.exports = function (options) {
    var servers = options.servers;
    var dest = options.dest;
    var shell = options.shell;
    var logPath = options.logPath;

    return through.obj(function (file, enc, callback) {
        if (file.isNull()) {
            callback(null, file);
            return;
        }

        if (file.isStream()) {
            return callback(new gutil.PluginError(PLUGIN_NAME, 'No stream support'));
        }

        var i = 0;
        async.eachSeries(servers, function(server, done) {
            var hostName = server.sshConfig.host;
            gutil.log(PLUGIN_NAME, "start deploy:" + hostName)
            var client = new ScpClient(server.sshConfig);

            var bar = null;
            client.on("transfer",  function(buffer, uploaded, total){
                if(bar == null){
                    bar = new ProgressBar(hostName + ' uploading [:bar] :percent :elapsed s', {
                        complete: '=',
                        incomplete: ' ',
                        width: 50,
                        total: total
                    });
                }
                bar.tick(1);
            });
            
            client.write({
                destination: dest,
                content: file.contents
            }, function () {
                ssh(server).shell(shell, {filePath: logPath + "-" + hostName + ".log", autoExit: true}).on('error', function (err) {
                    done(err);

                    gutil.PluginError(PLUGIN_NAME,  err)
                }).on('finish', function () {
                    gutil.log(PLUGIN_NAME, "finish deploy:" + hostName);

                    done();

                    if (++i === servers.length) {
                        callback(null, file);
                    }
                }).pipe(gulp.dest('logs'));
            });
        });

    });

};

    deploy-ssh 主要用于上传发布包至服务器并登录服务器之行发布脚本。

    6.在项目根目录创建 deploy-config.js

$ touch deploy-config.js

    添加以下内容:

var config = {
    production:{
        servers:[
        {
            sshConfig: {
                host: '172.16.70.174',
                port: 22,
                username: 'admin',
                password: 'cavin@123',
                readyTimeout: 200000
            }
        }]
    }
};

module.exports = config;

    deploy-config 主要用于配置deploy服务器信息。

    7.修改 gulpfile.js

     添加以下内容:

var gulp = require('gulp');
var shell = require('gulp-shell');
var ssh = require('gulp-ssh');
var deployConfig = require("./deploy-config");
var gulpSequence = require('gulp-sequence');
var zip = require('gulp-zip');
var through = require('through2');
var async = require('async');
var scpClient = require('scp2');
var gulpUtil = require('gulp-util');
var deploySSH = require('./deploy-ssh');

const PLUGIN_NAME = 'gulp-deploy ::'

gulp.task('default', shell.task([
  'DEBUG=express-demo:* npm start'
]));

gulp.task('production', function (){
   shell.task(['rm -rf dist']);
   gulpSequence('copyFile', 'zipFile', 'deploy',  function() {
       gulpUtil.log(PLUGIN_NAME, "***** Deploy Finished!!!!");
       process.exit(0);
    });
});

gulp.task('copyFile', function() {
    return gulp.src(
            [
                '*.json',
                '*.js',
                'routes/**',
                'views/**',
                'public/**',
                '!config.js'
            ], { base: './'})
            .pipe(gulp.dest('./dist'));
});

gulp.task('zipFile', function() {
    return gulp.src(['dist/**'], { base: './' })
            .pipe(zip('publish.zip'))
            .pipe(gulp.dest('./dist'));
});

gulp.task('deploy', function() {
    var config = deployConfig.production;
    config.deployPath = '/home/admin/publish/web/express-demo/';
    return gulp.src("dist/publish.zip", { base: './' })
            .pipe(deploySSH({
                servers: config.servers,
                dest: config.deployPath + 'publish.zip',
                logPath: 'deploy',
                shell:[ 'cd ' + config.deployPath,
                        'shopt -s extglob',
                        'rm -rf !(logs|node_modules|config.js|publish.zip)',
                        'unzip -o publish.zip',
                        'cp -rf dist/** .',
                        'rm -rf dist',
                        "rm publish.zip",
                        'npm install --production',
                        'pm2 startOrRestart pm2-start.json'],
            }));
});

    主要 gulp 任务流程为:

        1)拷贝文档至临时目录

        2)压缩文件

        3)发布(先上发布包,然后远程登录服务器之行发布脚本)

    注:发布目录 '/home/admin/publish/web/express-demo/' 一定要存在,否则scp上传文件时会出错。

四、一键部署 express-demo    

    执行发布任务

$ gulp production

    如果没有错误,登录服务器上面可以看到:

$ pm2 list
┌──────────────┬────┬─────────┬──────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name     │ id │ mode    │ pid  │ status │ restart │ uptime │ memory      │ watching │
├──────────────┼────┼─────────┼──────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ express-demo │ 0  │ cluster │ 2537 │ online │ 0       │ 102s   │ 30.117 MB   │ disabled │
│ express-demo │ 1  │ cluster │ 2542 │ online │ 0       │ 102s   │ 30.133 MB   │ disabled │
│ express-demo │ 2  │ cluster │ 2543 │ online │ 0       │ 102s   │ 30.109 MB   │ disabled │
│ express-demo │ 3  │ cluster │ 2544 │ online │ 0       │ 102s   │ 30.363 MB   │ disabled │
└──────────────┴────┴─────────┴──────┴────────┴─────────┴────────┴─────────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

    在浏览器里面输入:http://172.16.70.174:3000/


项目代码:https://git.oschina.net/cavintang/express-demo.git


你可能感兴趣的:(centos,express,node.js,gulp,pm2)