2013年9月19日 星期四

如何在Ubuntu 13.04 Server上部署Ruby on Rails app


剛好最近幫朋友架設Ruby on Rails Server,查了不少資料,發現Rails的設定真的有點麻煩。所以把rails的設定方法寫下來,免的日後自己忘記。

如果想要全面的理解部署方案,可以參考這篇stackoverflow的文章:
http://stackoverflow.com/questions/4113299/ruby-on-rails-server-options/4113570



概觀


首先,要說明一下架構。架構分為兩種,一種是使用Nginx的Passenger模組,以類似Apache的php_mod模式來執行rails application server。如下圖:



說明一下圖中的步驟:

1.Nginx經由port 80收到瀏覽器送來的要求
2.Nginx使用Passenger把要求送到rails application server
3.Nginx使用Passenger去取得rails application server的回應
4.Nginx把回應送回去給瀏覽器

這種方式最大的缺點,在於Ubuntu預設的Nginx沒有辦法使用Passenger模組,必須要額外安裝別人打包好的Nginx。



另外一種是使用Unicorn另外監聽socket,當Nginx收到訊息後,透過socket的方式傳給Unicorn後,由Unicorn傳回rails application server的回應,再把這個回應傳回到瀏覽器。



說明一下圖中的步驟:

a.Unicorn啟動的時候,會載入rails application server的設定
b.Unicorn接著設置好監聽的socket

1.Nginx經由port 80收到瀏覽器送來的要求
2.Nginx把要求經過設置好的socket轉送到Unicorn
3.Unicorn把rails application server的回應透過socket轉送給Nginx
4.Nginx把回應送回去給瀏覽器

以下就這兩者來進行部署的設置說明。

首先要說明幾個目錄的設置位置,如有需要可以自行更換:

rails application server:
/srv/rails/app
unicorn socket
/var/run/unicorn.sock
unicorn pid
/var/run/unicorn.pid

安裝Ruby


首先,要先安裝ruby。雖然ubuntu自己也有提供ruby,但是ruby每個版本不太一樣,會有相容性的問題;因此建議使用rvm的方式來安裝。

又由於這是以VPS為例,因此建議把rvm裝在系統上,而不是在家目錄裡。

首先安裝rvm,先切換為root後執行:

curl -L https://get.rvm.io | bash -s

如果想要同時安裝ruby,可以執行:

curl -L https://get.rvm.io | bash -s stable --ruby

接著編輯/etc/profile

vi /etc/profile

在最後面加入:

source /usr/local/rvm/scripts/rvm

接著檢查相依性,並自動安裝缺少的軟體:

rvm requirements

額外安裝缺少的軟體:

sudo apt-get install libxslt-dev libxml2-dev libsqlite3-dev

安裝2.0.0的ruby:

rvm install ruby-2.0.0-p247

設定為預設ruby

rvm --default use 2.0.0

安裝rubygems方便後續安裝軟體

rvm rubygems current

安裝rails

gem install rails --version 4.0.0

安裝完rails以後,由於rails需要在機器中直接執行javascript程式碼,因此需要有javascript的直譯器。推荐使用nodejs作為javascript的直譯器。

安裝nodejs


安裝nodejs有兩種方式。在ubuntu上可以添加apt repository安裝,也可以使用nvm的方式進行安裝。

以添加apt repository的方式安裝

依序執行以下命令,就可以apt-get的方式安裝node.js
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs

以nvm的方式安裝

先安裝缺少的git,才能接著安裝。
sudo apt-get install git

下載nvm並且安裝
curl https://raw.github.com/creationix/nvm/master/install.sh | sh

列出目前可以安裝的node版本
nvm ls-remote

安裝0.11.7版
nvm install 0.11.7

使用並設置為預設nodejs
nvm use 0.11.7
nvm alias default 0.11.7

如果今天是在VPS環境上,可以執行以下指令,把目前使用中的nodejs複製到/usr/local底下,未來就不用載入nvm,就可以使用當前版本的nodejs了。
n=$(which node);n=${n%/bin/node}; chmod -R 755 $n/bin/*; sudo cp -r $n/{bin,lib,share} /usr/local

Passenger的安裝方式


由於passenger的官方apt repository使用的是https,不是普通的http,因此要先幫ubuntu安裝缺少的軟體
sudo apt-get install apt-transport-https

接著匯入金鑰,這樣才能認証軟體是不是正確的
gpg --armor --export 561F9B9CAC40B2F7 | sudo apt-key add -

接著編輯repository檔案:
vi /etc/apt/sources.list.d/passenger.list

寫入:
deb https://oss-binaries.phusionpassenger.com/apt/passenger raring main

修正權限
sudo chown root: /etc/apt/sources.list.d/passenger.list
sudo chmod 600 /etc/apt/sources.list.d/passenger.list

更新並安裝module
sudo apt-get update
sudo apt-get install nginx-full passenger

為ruby添加passenger支援
gem install passenger

最後,修改Nginx網站設置:

vi /etc/nginx/site-enable/default
修改如下:
http {
    ...
    server {
        listen 80;
        server_name www.example.com;
        root /srv/rails/app/public;
        passenger_enabled on;
    }
    ...
}

使用Unicorn的安裝方式


安裝nginx

sudo apt-get install nginx

安裝 unicorn

sudo apt-get install unicorn

unicorn有兩個設置檔:
一個是/etc/default/unicorn,另外一個放在app目錄中,路徑為/srv/rails/app/unicorn.conf.rb

首先修改/etc/default/unicorn

vi /etc/default/unicorn

修改底下的項目和值,成這個樣子:
CONFIGURED=yes
APP_ROOT=/srv/rails/app

接著抓下unicorn.conf.rb的設置範本到app的目錄中

curl -o /srv/rails/app/unicorn.conf.rb https://raw.github.com/defunkt/unicorn/master/examples/unicorn.conf.rb

修改這個檔案的幾個值。注意socket和pid檔案的位置要對。

vi /srv/rails/app/unicorn.conf.rb

working_directory "/srv/rails/app"
listen "/var/run/unicorn.sock", :backlog => 64
pid "/var/run/unicorn.pid"
stderr_path "/var/log/unicorn.stderr.log"
stdout_path "/var/log/unicorn.stdout.log"

最後,修改Nginx的網站檔案:

vi /etc/nginx/site-enable/default

upstream unicorn {
  server unix:/var/run/unicorn.sock fail_timeout=0;
}

server {
  listen 80;
  server_name www.example.com; # 網站的 URL
  root /srv/rails/app/public; # App放置位置
  location / {
    proxy_pass http://unicorn; # 和前面的upstream欄位要相同
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
  ...
}


設置monit監控


由於server上的各種服務可能會因為bug而失控,導致server當機,因此可以安裝monit來監控server狀況,在服務出問題的時候重開。

首先,安裝monit
sudo apt-get install monit

如果使用Passenger,只要監控Nginx就好,而monit已經有Nginx的監控設置檔了。如果使用的是Unicorn,就需要特別設定設置檔來設定monit監控unicorn。

vi /etc/monit/monitrc.d/unicorn

修改內容為:

check process unicorn
  with pidfile /var/run/unicorn.pid
  start program = "/etc/init.d/unicorn start"
  stop program = "/etc/init.d/unicorn stop"
  group unicorn

如果想要更進階的監控unicorn的worker,可以參考這裡。
http://shapeshed.com/managing-unicorn-workers-with-monit/

參考資料:
http://ruby.railstutorial.org/ruby-on-rails-tutorial-book
https://www.digitalocean.com/community/articles/how-to-install-rails-and-nginx-with-passenger-on-ubuntu
http://www.modrails.com/documentation/Users%20guide%20Nginx.html
http://tomkersten.com/articles/nginx-unicorn-rvm-server-setup/
http://linuxmoz.com/ubuntu-ruby-on-rails-nginx-unicorn/
http://sirupsen.com/setting-up-unicorn-with-nginx/
http://stackoverflow.com/questions/768184/god-vs-monit

1 意見:

Frank Xu 提到...

You can try Capistrano next time to deploy it automaticlly.XD Here is the link: http://www.capistranorb.com/