Rails2 から Rails3 へ引越し

kozuchi という家計簿Webアプリケーションを自分のサーバにインストールして利用している.大変便利でありがたく利用させて頂いている.
Railsアプリケーションを自分で書くことはなく,このアプリケーションをインストールするために学んだ程度なので,細かいことが分かっていない.今回,サーバ引越しで環境が変わりセットアップをやり直したのでメモしておく.実際は FreeBSD の Jail 環境内に構築したがそこの説明は今回は省略.

移行前後の kozuchi のバージョンが違い,データベースのスキーマなどが変更されていてまだ動作していないのだけれど,とりあえずメモ.

新環境 Rails3 のセットアップ

git, ruby19, ruby-gems 等を ports からインストールしておく.DB には sqlite3,HTTPのフロントエンドサーバには nginx を利用するので,これらも ports からインストールする.
railsports も有るようだがこれは使わずに,bundler という管理ツールを利用してインストールした.bundler については http://memo.yomukaku.net/entries/IpCSQmo がとても分かり易かった.gem で bundler をインストールし,git clone した kozuchi ルート直下の Gemfile を少し修正して bundle install すると必要な gem をインスールされる.

# gem install bundler
% cd /home
% git clone https://github.com/everyleaf/kozuchi.git
% cd kozuchi
% vi Gemfile
(必要に応じて修正.今回は mysql ではなく sqlite3 を使うための修正と unicorn を利用する修正をした)
% bundle install --path vendor/bundle

bundle を利用すると,gem のインストール先をシステムデフォルトの位置から変えることができ,しかも今後は特に意識することなく指定した位置で固定しておくことができるらしい.ただし,そうやってインストールされた gem を利用する時は下記のように bundle exec 経由で実行する必要がある.これはちょっと面倒だが "be" などエイリアス登録しておくのが良いのか.

% bundle exec rake
% bundle exec unicorn_rails

nginx と unicorn

nginx をフロントエンドに置き,unicorn のマスターがロードバランサーunicorn の子プロセスがバックエンドとなって動作するらしい.この辺の説明が分かりやすい.nginx と unicorn 間の通信は TCP socket と unix domain socket が選べる.わずかだが後者の方が高速なはずなので後者で.
まずは nginx の設定ファイル.

# cat /usr/local/etc/nginx/nginx.conf | sed -e 's/#.*$//g' -e 's/^[[:space:]]*$//g' | grep -v '^$'
user  www;
worker_processes  5;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    access_log  /var/log/nginx-access.log;
    error_log   /var/log/nginx-error.log;
    sendfile        on;
    keepalive_timeout  65;
    upstream kozuchi {
      server unix:/home/kozuchi/tmp/sockets/unicorn.sock;
    }
    server {
      listen 80;
      server_name _; 
      location ~* \.(html|ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
        root /home/kozuchi/public;
        expires 1y;
        add_header Cache-Control public;
        add_header ETag "";
        break;
      }
      location / {
        if (-f $request_filename) { break; }
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
        proxy_pass http://kozuchi.example.com;
        proxy_redirect off;
      }
    }
}

proxy_set_header Host のところは $host とする例を見ることが多かったが,ssh port forward などでポート番号を変更して利用する環境ではHTTPリダイレクト時にポート番号が追従しないので,$http_host に変更した.http://localhost:3000/ にアクセスしている場合,$host='localhost',$http_host='localhost:3000' となる.
次に unicorn の設定ファイル.再起動時の処理などもカスタマイズできるようだが,自分で使うだけのサーバなのでその辺は適当に手動対応.

% cat config/unicorn.rb
ROOT_PATH='/home/kozuchi'
worker_processes 5
listen          ROOT_PATH+'/tmp/sockets/unicorn.sock'
pid             ROOT_PATH+'/tmp/pids/unicorn.pid'
stderr_path     ROOT_PATH+'/log/unicorn.log'
stdout_path     ROOT_PATH+'/log/unicorn.log'

起動は以下のように.-E オプションの付け忘れに注意.

# /usr/local/etc/rc.d/nginx start
% cd kozuchi
% bundle exec unicorn_rails -c config/unicorn.rb -E production

yaml_db

旧環境(Rails2 + mysql) から新環境(Rails3 + sqlite3)へ移行するため,既存データの移行が必要になった.データベースが異なるので単純なdump&restoreができない.こういう時のために,yaml_dbというgemが用意されていた.ありがたや.
Rails2 と Rails3 ではこの gem をインストールする手順が違うのでちょっとつまずいた.普段からRailsを開発で使っている人はつまずかないんだろうけど.
Rails2 に yaml_db を入れてDBをダンプ.db/schema.rb と db/data.yaml が作成されるので新環境の db/ へコピー.

% script/plugin install git://github.com/adamwiggins/yaml_db.git
% rake db:data:dump RAILS_ENV=production

Rails3 に yaml_db を入れてリストア.

% echo "gem 'yaml_db'" >> Gemfile
% bundle install
% bundle exec rake db:data:load RAILS_ENV=production