天天看點

部署Node.js的應用

最近Node.js很火,讓很多的前端看到了可以直接從前端寫到後端的希望。但是每次部署一個Node.js的應用卻讓前端苦惱不已。 每次登陸伺服器,用自己不熟悉的方式從版本控制倉庫中拖下源代碼,kill掉應用的程序,重起一個應用的守護程序。如果能夠自動化的部署一個Node.js應用,而不需要去接觸這些前端不太熟悉的Unix系統指令和管理。對于大家來說就是提升了生産力。Capistrano是一個強大的自動化部署工具,是以我們選用他來做自動化部署。并且我已經把做好了的一個部署腳本Nodebot送出到github上去,供大家參考。 首先我們需要一個環境,分為兩個環境:部署用戶端環境和伺服器環境。

部署用戶端系統需求:

你可以用任何系統了,系統隻要具備下面的4個軟體就可。

  1. 安裝ruby。去http://www.ruby-lang.org/en/downloads/下載下傳适合你系統的ruby版本。
  2. 安裝rubygem。去http://rubyforge.org/projects/rubygems/下載下傳最新版的RubyGems,解壓後運作以下指令安裝。 sudo ruby setup.rb
  3. 安裝Capistrano和Capistrano-etx。運作以下的指令安裝。sudo gem install capistrano capistrano-ext

這樣你就擁有了在機器部署node.js應用的軟體。然後你需要能夠不使用密碼直接登陸到伺服器上。運作下面的指令:

# Create a local ssh key 
ssh-keygen 
#Copy key to server 
cat ~/.ssh/id_rsa.pub | ssh [email protected] “cat >> .ssh/authorized_keys”       

這樣你就可以不需要密碼直接登陸到伺服器。

伺服器端系統需求:

當然要Unix一類的系統了,Nodebot需要具備upstart的系統(一個基于事件的守護程序管理系統)。雖然Node.js能跑在window上,但是那隻适合開發環境,不适合生産環境。還要有下面的軟體,你也可以下載下傳Nodebot并在部署用戶端運作指令cap nodebot:setup 來自動化安裝。

  1. 安裝scm軟體。比如git,svn或hg,取決于你的node.js應用源代碼管理軟體。
  2. 安裝Node.js。沒什麼好說的,地球人都知道這是什麼。
  3. 安裝npm。Node.js的一個包管理軟體
  4. 安裝node-jake。一個javascript的代碼建構工具,有點像make和rake。用來安裝應用的依賴。
  5. 具備upstart的系統,比如Ubantu。來做應用的守護程序。參看 http://upstart.ubuntu.com/

部署的登陸使用者需要sudo權限,并且不需要提示輸入密碼。參考指令:

#Add a sudoer 
sudo useradd -m foo 
#edit sudoer privilege 
sudo visudo       

出現編輯器時,插入下面一行,foo就是你建立的使用者:

foo ALL=(ALL) NOPASSWD: ALL      

然後在deploy.rb檔案(下面會提到)裡配置foo為部署使用者。

部署用戶端腳本

環境有了,那就要開工了。我們希望在伺服器上的Node.js應用運作幾個不同的環境:測試環境,開發環境,産品環境等。運作cap .指令會在目前的目錄下産生一個檔案和一個目錄。在目錄裡有個deploy.rb,這是我們需要修改的檔案。由于我們需要多個環境,是以我們引入了Capistrano-etx。

set :stages, %w[staging production] 
set :default_stage, ‘staging’ 
require ‘capistrano/ext/multistage’       

我們設定了兩個環境:staging和production,預設是staging環境。我們再在config目錄下建一個deploy目錄,裡面放的兩個.rb檔案對應不同的環境配置.最後部署環境的目錄下是這樣的一個結構:

. 
├── Capfile 
└── config 
 ├── deploy 
 │   ├── production.rb 
 │   └── staging.rb 
 ├── deploy.rb 
 └── node.rb
      

  

deploy.rb檔案看起來像這樣。你需要設定host, repository,user和admin_user :

## 
# Capistrano tasks for Ubantu. 
# 
# Author: Shihua Ma http://f2eskills.com/ 
 
set :stages, %w[staging production] 
set :default_stage, ‘staging’ 
require ‘capistrano/ext/multistage’ 
#application name 
set :application, “example” 
#start server script 
set :node_file, “app.js” 
#deploy host 
set :host, “hostname” 
#user name,must be a sudoer without prompting for password 
set :user, “username” 
set :admin_runner, user 
 
 
set :repository, “git@[email protected]:mashihua/Nodebot.git” 
set :scm, :git 
set :deploy_via, :remote_cache 
role :app, host 
set :use_sudo, true 
 
namespace :deploy do 


 desc “Start node server” 
 task :start, :roles => :app, :except => { :no_release => true } do 
 run “sudo start #{application}#{node_env}" 
 end 


 desc “Stop node server” 
 task :stop, :roles => :app, :except => { :no_release => true } do 
 run "sudo stop #{application}#{node_env}” 
 end 


 desc “Restart node server” 
 task :restart, :roles => :app, :except => { :no_release => true } do 
 run “sudo restart #{application}#{node_env} || sudo start #{application}#{node_env}” 
 end 
 
 desc “Check required packages and install if packages are not installed” 
 task :check_packages, roles => :app do 
 run “cd #{release_path} && jake depends” 
 end 
 
 task :create_deploy_to_with_sudo, :roles => :app do 
 run “sudo mkdir -p #{deploy_to}” 
 run “sudo chown #{admin_runner}:#{admin_runner} #{deploy_to}” 
 end 
 
 desc “Update submodules” 
 task :update_submodules, :roles => :app do 
 run “cd #{release_path}; git submodule init && git submodule update” 
 end 


 task :write_upstart_script, :roles => :app do 
 upstart_script = <> #{shared_path}/log/#{node_env}.log 2>&1" 
end script 
respawn 
UPSTART 
 
 put upstart_script, “/tmp/#{application}_upstart.conf” 
 run “sudo mv /tmp/#{application}upstart.conf /etc/init/#{application}#{node_env}.conf” 
 end 
 
end 
 
before ‘deploy:setup’, ‘deploy:create_deploy_to_with_sudo’ 
after ‘deploy:setup’, ‘deploy:write_upstart_script’ 
after “deploy:finalize_update”, “deploy:update_submodules”, “deploy:check_packages” 
      

staging.rb環境檔案看起來像這樣。設定了應用的環境,git的branch,應用的監聽端口和部署目錄:

set :node_env, “staging” 
#git repos branch 
set :branch, “master” 
#listing port 
set :application_port, “1603” 
#deploy path 
set :deploy_to, “/srv/www/apps/#{application}/#{node_env}” 
      

production.rb環境檔案看起來像這樣:

set :node_env, “production” 
#git repos branch 
set :branch, “production” 
#listing port 
set :application_port, “1604” 
#deploy path 
set :deploy_to, “/srv/www/apps/#{application}/#{node_env}” 
      

主要指令:

  • cap -T 檢視所有的task
  • cap deploy:setup 設定staging環境,比如建立部署的目錄等。staging是預設環境,指令等同于cap staging deploy:setup。調用production環境的指令cap production deploy:setup,第一個參數是環境名,第二個參數是任務名。
  • cap nodebot:setup 安裝系統一些軟體和配置守護程序。上面已經介紹過。
  • cap production deploy 部署 production環境的Node.js應用。包括從倉庫取最新的代碼,連結最新的代碼到一個目錄。重起應用的Server。
  • cap deploy:stop, cap deploy:start和cap deploy:restart 停止,啟動和重起staging環境的Server。

簡單的Node.js應用:

我們用一個簡單的Node.js應用來說明實際的效果,應用的目錄結構就像這樣:

. 
├── Jakefile.js 
├── app.js 
├── config 
│   └── requirements.json 
└── log
      

log 應用日志的輸出目錄 app.js 就是應用的啟動腳本

var express = require(‘express’); 
 
var app = express.createServer(); 
 
app.get(’/’, function(req, res){ 
 //the log will out put to log/{node_env}.log 
 console.log(“Method:” + req.method); 
 //send text to agent 
 res.send(‘Hello World. NODE_ENV=’ + process.env.NODE_ENV); 
}); 
 
 
//listening on application_port where set by capistrano 
app.listen(process.argv[2] || 3000); 
      

Jakefile.js jake建構工具調用的腳本,在本例子中用來安裝express

var fs = require(‘fs’); 
 
desc(‘Check and install required packages’); 
task(‘depends’, [], function (arg) { 
 var npm = require(‘npm’); 
 npm.load({}, function (err) { 
 if (err) return commandFailed(err); 
 npm.on(“log”, function (message) { if(arg) console.log(message) }) 
 var requirements = JSON.parse(fs.readFileSync(‘config/requirements.json’)); 
 npm.commands.install(requirements, function (err, data) { 
 if (err) return commandFailed(err); 
 }); 
 }); 
}, true); 
      

config/requirements.json 應用依賴的定義

[ “[email protected]”]
      

實際部署的效果: staging環境, production環境

結論:

使用Nodebot你可以輕松的部署你的Node.js應用。把你的焦點放到實際的需求中,而不用關心部署環境的建立和部署應用的麻煩,隻許在部署用戶端輕松的輸入簡單的指令。