使用Heroku+mLab 部署Node應(yīng)用

問(wèn)題背景

最近嘗試了一下node.js,迷迷糊糊,不太懂,所以干脆找一個(gè)基于node.js平臺(tái)的小項(xiàng)目做一下,我大概掃了一眼javascript的基礎(chǔ)和node.js的介紹,然后在GitHub上找到了一個(gè)非常詳實(shí)的項(xiàng)目:nswbmw/N-blog,根據(jù)他的講解,一步一步實(shí)現(xiàn)了多人博客的基礎(chǔ)雛形,之后我使用Bootstrap進(jìn)行了美化,做了一個(gè)關(guān)于行尸走肉的多人博客網(wǎng)頁(yè),利用標(biāo)簽的特性,實(shí)現(xiàn)了各個(gè)頻道的檢索。

N-Blog-WalkingDeading_01.jpg

真打算布置到nswbmw所使用的Heroku和MongoHQ,但是MongoHQ目前好像已經(jīng)不能使用了,于是在網(wǎng)上找到了他的替代品mLab,看了下相關(guān)的教程幾乎和已經(jīng)消失的MongoHQ的使用步驟是一致的,但是網(wǎng)上教程大多使用的Ubuntu系統(tǒng),我這里使用的Windows,并且多數(shù)使用mongoose來(lái)進(jìn)行MongoDB數(shù)據(jù)庫(kù)操作,看的我云里霧里,正好剛剛部署成功。這里簡(jiǎn)單介紹下,使用mLabHeroku分別進(jìn)行MongoDB和node部署的過(guò)程。
這里還是參照nswbmw/N-blog的wiki上的例子的順序,首先將本地MongoDB切換到mLab上。

使用mLab

mLab登陸.jpg

SignUp注冊(cè),我使用的是網(wǎng)易126郵箱,可以進(jìn)行申請(qǐng),申請(qǐng)后需要發(fā)送一個(gè)確認(rèn)的郵件,進(jìn)入你的郵件去找到,然后訪問(wèn)返回的連接。

注冊(cè).jpg

注意注冊(cè)時(shí),這里分別有Account name和Username,一定要注意了,一會(huì)Log In登陸的時(shí)候,使用的Username。


登陸后.jpg

我因?yàn)橐呀?jīng)注冊(cè)了,直接進(jìn)入時(shí)這個(gè)樣子,選擇MongoDB Deployments(數(shù)據(jù)庫(kù)部署)下的Create New,創(chuàng)建新的數(shù)據(jù)庫(kù)。


選擇數(shù)據(jù)庫(kù)大小.jpg

這里選擇你需要的云服務(wù)商和區(qū)域,本來(lái)打算選擇新加坡的服務(wù)區(qū)域,但是在Region中選擇Amazon's Asia Pacific(Singapore)Region(ap-southeast-1),會(huì)發(fā)現(xiàn)沒(méi)有免費(fèi)的,大概看了下,只有美國(guó)區(qū)選擇Plan中的Single—node,才可以選擇免費(fèi)的0.5GB的Sandbox。
選擇已經(jīng)建好的數(shù)據(jù)庫(kù).jpg

選擇已經(jīng)建好的進(jìn)入數(shù)據(jù)庫(kù),需要新建使用數(shù)據(jù)庫(kù)的用戶名和密碼,然后是非常關(guān)鍵的問(wèn)題,就是如下:
新建數(shù)據(jù)庫(kù)使用者用戶.jpg

提示你了,如何切換數(shù)據(jù)庫(kù)到mLab,我這里使用的To connect using a driver via the standard MongoDB URI (what's this?):這個(gè)選項(xiàng)

直接點(diǎn)擊what's this?進(jìn)入幫助文檔,然后向下找到下面的MongoDB driver(可以Ctrl+F)選擇其中的 driver examples in many of the major languages

MongoDB driver

In order to provide your application a means to communicate with your MongoDB database, you will need a driver in a language appropriate to your application.

You can go to MongoDB, Inc.’s site to read about the official MongoDB drivers, but we also provide driver examples in many of the major languages: C#, Java, Node.js, PHP, Python, Ruby, etc.. These examples should run out-of-the-box after you install the appropriate driver(s) and update your MongoDB URI.

You may find our troubleshooting guide helpful if you continue to experience problems trying to connect to your deployment using a compatible driver.

之后進(jìn)入語(yǔ)言中心,這里的語(yǔ)言中心不是指設(shè)置中英文,而是指的是編程語(yǔ)言

Language Center

Node.js

The officially supported Node.js Native driver for MongoDB:

CRUD example
Mongoose, an Object Document Mapper (ODM) for MongoDB:

Mongoose CRUD example
Mongoose Tips & Tricks (from mLab’s blog)

點(diǎn)擊鏈接CRUD example,就可以看到node.js如何連接數(shù)據(jù)庫(kù)了,下邊就是CRUD example點(diǎn)擊后的全部文檔,講了如何在node中使用mLab數(shù)據(jù)庫(kù)作為外部數(shù)據(jù)庫(kù)的方法:

/*
 * Copyright (c) 2016 ObjectLabs Corporation
 * Distributed under the MIT license - http://opensource.org/licenses/MIT
 *
 * Written with: mongodb@2.1.3
 * Documentation: http://mongodb.github.io/node-mongodb-native/
 * A Node script connecting to a MongoDB database given a MongoDB Connection URI.
*/

var mongodb = require('mongodb');

// Create seed data

var seedData = [
  {
    decade: '1970s',
    artist: 'Debby Boone',
    song: 'You Light Up My Life',
    weeksAtOne: 10
  },
  {
    decade: '1980s',
    artist: 'Olivia Newton-John',
    song: 'Physical',
    weeksAtOne: 10
  },
  {
    decade: '1990s',
    artist: 'Mariah Carey',
    song: 'One Sweet Day',
    weeksAtOne: 16
  }
];

// Standard URI format: mongodb://[dbuser:dbpassword@]host:port/dbname

var uri = 'mongodb://user:pass@host:port/db';

mongodb.MongoClient.connect(uri, function(err, db) {
  
  if(err) throw err;
  
  /*
   * First we'll add a few songs. Nothing is required to create the 
   * songs collection; it is created automatically when we insert.
   */

  var songs = db.collection('songs');

   // Note that the insert method can take either an array or a dict.

  songs.insert(seedData, function(err, result) {
    
    if(err) throw err;

    /*
     * Then we need to give Boyz II Men credit for their contribution
     * to the hit "One Sweet Day".
     */

    songs.update(
      { song: 'One Sweet Day' }, 
      { $set: { artist: 'Mariah Carey ft. Boyz II Men' } },
      function (err, result) {
        
        if(err) throw err;

        /*
         * Finally we run a query which returns all the hits that spend 10 or
         * more weeks at number 1.
         */

        songs.find({ weeksAtOne : { $gte: 10 } }).sort({ decade: 1 }).toArray(function (err, docs) {

          if(err) throw err;

          docs.forEach(function (doc) {
            console.log(
              'In the ' + doc['decade'] + ', ' + doc['song'] + ' by ' + doc['artist'] + 
              ' topped the charts for ' + doc['weeksAtOne'] + ' straight weeks.'
            );
          });
         
          // Since this is an example, we'll clean up after ourselves.
          songs.drop(function (err) {
            if(err) throw err;
           
            // Only close the connection when your app is terminating.
            db.close(function (err) {
              if(err) throw err;
            });
          });
        });
      }
    );
  });
});

我們主要使用的是如何連接數(shù)據(jù)庫(kù),所以下邊的這個(gè)尤其重要:

var uri = 'mongodb://user:pass@host:port/db';
mongodb.MongoClient.connect(uri, function(err, db) {
……
}

這里開(kāi)始就不再與nswbmw/部署到Heroku的wiki上一致,其余參照nswbmw/部署到Heroku,
修改 settings.js 為:
module.exports = {
cookieSecret: 'myblog',
url: 'your_Mongo_URI'
};
將 your_Mongo_URI 替換為你自己創(chuàng)建的數(shù)據(jù)庫(kù)的 URL ,將 <user> 和 <password> 分別替換為剛才添加的用戶的名字和密碼。
我的是

module.exports = {
    cookieSecret: 'myblog',
    url: 'mongodb://54wallis_a_good_man:haha@ds015869.mlab.com:15869/walkingdead'
};

需要注意

mongodb://<dbuser>:<dbpassword>@ds015869.mlab.com:15869/walkingdead

這里的兩個(gè)<>都是要去掉的。
nswbmw/N-blog講的如下:
打開(kāi) app.js ,將 app.use(express.session(...)); 修改為:
app.use(express.session({
secret: settings.cookieSecret,
cookie: {maxAge: 1000 * 60 * 60 * 24 * 30},//30 days
url: settings.url
}));
刪除 db.js ,打開(kāi) post.js 、 user.js 和 comment.js ,均作以下修改:
將 mongodb = require('./db') 修改為 mongodb = require('mongodb').Db
添加 var settings = require('../settings');
將所有 mongodb.open(function (err, db) { 修改為 mongodb.connect(settings.url, function (err, db) {
將所有 mongodb.close(); 修改為 db.close();

這里不能完全參照改教程了,需要按最新的mLab要求進(jìn)行修改,
將 上邊所有的mongodb = require('./db') 修改為 mongodb = require('mongodb');
就是將所有 mongodb.open(function (err, db) { 修改為 mongodb.MongoClient.connect(settings.url, function (err, db) {
其余同nswbmw/N-blog,這里就可以完成了。
現(xiàn)在,無(wú)需啟動(dòng)你的mongo本地?cái)?shù)據(jù)庫(kù),直接啟動(dòng)你的多人博客或者其他node應(yīng)用,會(huì)比較慢,就可以看到了,像一起一樣可以增加修改,而在mlab可以看到你的數(shù)據(jù)庫(kù)。


mLab數(shù)據(jù)庫(kù).jpg

部署到 Heroku

Heroku 支持很多語(yǔ)言的部署,下面使用 Heroku 部署我們的博客。我這里完全沒(méi)有安裝Heroku Toolbelt,也沒(méi)有用到git bash,直接全部在網(wǎng)頁(yè)中執(zhí)行。過(guò)程與nswbmw/N-blog稍有不同。

使用Webstorm的提醒

我行為是直接使用Webstorm新建Express項(xiàng)目,所以特別需要注意,Webstorm直接運(yùn)行的是bin文件夾中的www文件,打開(kāi)www文件,可以看到下邊一段代碼:

/* Get port from environment and store in Express.*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

這里相當(dāng)于指定了監(jiān)聽(tīng)接口,所以在app.js文件中就不能出現(xiàn)接口設(shè)置的代碼了:

/*增加app.set('port', process.env.PORT || 3000);
可以直接使用node app.js啟動(dòng)網(wǎng)頁(yè)了,但是在webStorm中就會(huì)報(bào)錯(cuò)*//
//app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(flash());

但是如果部署在Heroku或者直接在所在項(xiàng)目中直接node app.js 運(yùn)行項(xiàng)目的話,就必須在app.js中進(jìn)行注冊(cè)端口,所以必須有app.set('port', process.env.PORT || 3000);
否則無(wú)法node直接運(yùn)行,或者部署在Heroku時(shí),log的報(bào)錯(cuò)日志如下

2016-11-17T20:58:30.039234+00:00 app[web.1]: Thu, 17 Nov 2016 20:58:30 GMT express-session deprecated undefined resave option; provide resave option at app.js:16:9
2016-11-17T20:58:30.040264+00:00 app[web.1]: Thu, 17 Nov 2016 20:58:30 GMT express-session deprecated undefined saveUninitialized option; provide saveUninitialized option at app.js:16:9
2016-11-17T20:58:30.043619+00:00 app[web.1]: Warning: connect.session() MemoryStore is not
2016-11-17T20:58:30.043621+00:00 app[web.1]: designed for a production environment, as it will leak
2016-11-17T20:58:30.043621+00:00 app[web.1]: memory, and will not scale past a single process.
2016-11-17T20:58:30.094090+00:00 app[web.1]: Express server listening on port undefined
2016-11-17T20:59:28.281373+00:00 heroku[web.1]: State changed from starting to crashed
2016-11-17T20:59:28.161847+00:00 heroku[web.1]: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
2016-11-17T20:59:28.161908+00:00 heroku[web.1]: Stopping process with SIGKILL
2016-11-17T20:59:28.248754+00:00 heroku[web.1]: Process exited with status 137
2016-11-18T01:14:59.966727+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=walkingdead4android.herokuapp.com request_id=b6b28364-627c-4d08-a497-fdbceb890289 fwd="211.157.146.5" dyno= connect= service= status=503 bytes=

其中可以注意到:2016-11-17T20:58:30.094090+00:00 app[web.1]: Express server listening on port undefined,就是端口未定義。

新建Procfile

在工程的根目錄下新建一個(gè) Procfile 文件,添加如下內(nèi)容:

    web: node app.js

Procfile 文件告訴了服務(wù)器該使用什么命令啟動(dòng)一個(gè) web 服務(wù),這里通過(guò) node app.js 執(zhí)行 Node 腳本。

上傳到github

上傳項(xiàng)目到github上,注意在硬盤上的node完整項(xiàng)目的目錄如下:


項(xiàng)目結(jié)構(gòu).jpg

注意圖中上邊的文件夾時(shí)完整的,只需要上傳下邊的,上傳到github時(shí)把bin和node_modules這兩個(gè)文件夾除外,這兩文件較大,不需要上傳,bin是運(yùn)行node時(shí)生成的,而node_modules則是運(yùn)行node應(yīng)用時(shí)下載的依賴。

注冊(cè)Heroku

heroku首頁(yè).jpg

進(jìn)入Heroku,注冊(cè)注意我的126不能通過(guò),qq倒是可以。

創(chuàng)建一個(gè)應(yīng)用

注冊(cè)成功后,就進(jìn)入了控制面板頁(yè)面,如圖所示:

heroku新建app.jpg

點(diǎn)擊 New ,填寫?yīng)氁粺o(wú)二的應(yīng)用名稱后,點(diǎn)擊 Create App 即創(chuàng)建成功 。

heroku新建app2.jpg

點(diǎn)擊你的新建的這個(gè)app,然后選擇deploy(部署)這一項(xiàng),會(huì)遇到下邊的

heroku新建app3.jpg

因?yàn)轫?xiàng)目已經(jīng)上傳到GitHub上,所以,直接選擇GitHub,會(huì)進(jìn)行相應(yīng)的授權(quán)操作,然后在你的賬戶中選擇你要部署的項(xiàng)目所在的GitHub路徑,我這里是我的N-blog-WalkingDead

下邊僅跟著的就是兩種部署方式:

heroku新建app7自動(dòng)部署和一般部署.jpg

Automatic deploys 就是自動(dòng)部署,部署放生在更新你的GitHub,Heroku就會(huì)自動(dòng)部署,但是現(xiàn)在點(diǎn)擊它不會(huì)立刻馬上部署,可能會(huì)過(guò)幾分鐘之后,Manual deploy 就是一般性部署,點(diǎn)擊圖中的Deploy to Heroku就會(huì)立刻馬上部署。
這里在Manual deploy中進(jìn)行直接部署,點(diǎn)擊Show build log,就可以看到構(gòu)建的日志了,若果node項(xiàng)目(我這里是多人博客項(xiàng)目)沒(méi)有問(wèn)題,就可以你就可以訪問(wèn) http://yourAppName.herokuapp.com/ 進(jìn)行查看了。
我的項(xiàng)目結(jié)果如下:

N-Blog-WalkingDeading_02.jpg

手機(jī)端:
N-Blog-WalkingDeading_03.jpg

參考

利用heroku+mongoLab 部署Node 運(yùn)用
nswbmw/N-blog:番外篇之——部署到 Heroku
其余自行百度或谷歌。

廣告

鯉魚日語(yǔ)一個(gè)簡(jiǎn)單背日語(yǔ)的APP,歡迎下載,期待Star。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容