CentOS5.6 で MySQL+Nginx+Unicorn な Rails アプリを動かす
完全に自分用の備忘録。VirtualBox にインストールした CentOS5.6 に表題の環境を構築してサーバを動かすまで。
サーバのメモリは512Mでパーティションは40Gと、(記事執筆時では)一般的な低価格帯 VPS を意識したスペックに調整してあります。
また、すべての作業は su で root ユーザに昇格した上で行う前提になっているので sudo を使う場合適宜置き換えて下さい。
必要なパッケージのインストール
今後の作業に使うパッケージを yum からインストールしておきます。
yum install gcc gcc-c++ openssl* readline* ncurses* zlib* libxml* libjpeg* libpng* libxslt* libtool*
MySQL のインストール
これも yum からインストールします。
yum install mysql-server mysql-devel
mysql-devel を入れておかないと Ruby から MySQL を使う際にうまくいかないようです。インストールが完了したら my.cnf を修正します。
/usr/local/mysql/share/mysql 以下にサンプルが入っているので、好きなものを /etc/my.cnf としてコピーします。細かい設定については、今回は省略します。
次に MySQL を chkconfig の自動起動一覧に追加しておきます。
chkconfig mysqld on
これで、サーバの起動時に MySQL が(設定をミスしていなければ)自動起動するようになりました。
ここで MySQL の起動が正しく完了するか確認します。
/ect/rc.d/init.d/mysqld start
うまく起動すれば問題ありませんが、エラーになってしまう場合もあると思います。そのときは /var/log/mysqld.log にエラーの詳細が記述されているので、参考にして修正します(私の場合、データベースエンジンに innodb を指定したのですが、そのデータディレクトリが mysql ユーザ向けに作成されていなかったためエラーになりました)。
サービスの起動が完了したら、ルートユーザのパスワードを設定します。
/usr/bin/mysqladmin -u root password 'new-password' /usr/bin/mysqladmin -u root -h localhost password 'new-password' -p
new-password を好きなパスワードに書き換えて下さい。
設定した情報で MySQL を利用できるか確認してみます。
mysql -u root -p
設定がうまくいっていれば、パスワードの確認後に対話型インターフェースが立ち上がるはずです。
ImageMagick のインストール
Rails アプリから画像を扱いたいので ImageMagick をインストールします。
最新版をインストールしたいので、ソースをコンパイルします。ImageMagick のサイトから最新版の tgz をダウンロードして、インストールコマンドを実行します。
./configure --without-fpx make make install
私の環境では configure のオプションに --without-fpx をつけないとどうしてもインストールが成功しませんでした。
Python のインストール
easy_install に含まれる Pygments ライブラリを使いたいので Python をインストールします。
yum install python*
自動的に easy_install も使えるようになるのでインストールコマンドを実行。
easy_install pygments
Ruby のインストール
これも最新版を用いるので、ソースからインストール。特にオプションも必要なく make するだけで完了です。
RubyGems でライブラリを管理したいので、それもインストールします。ソースをダウンロードして展開したディレクトリ内に setup.rb というファイルが入っているので、実行します。
ruby setup.rb
Rails のインストール
Rails アプリの中核になる Ruby on Rails の gem をインストールします。
gem install rails
インストールが完了したら、動かす Rails アプリのルートディレクトリに移動して、他の使用する gem をインストールします。
bundle install
このとき JavaScript のランタイムが見つからないとエラーが発生する事がありますが、その場合 Gemfile に以下の行を追加してください。
gem install 'therubyracer'
その後、再度 bundle install を実行します。
ここまで完了したら config/database.yml を環境にあわせて修正した後で、データベースを初期化します。
bundle exec rake db:create:all RAILS_ENV=production bundle exec rake db:migrate RAILS_ENV=production bundle exec rake db:seed
また Rails 3.1 系のアセットパイプラインを使っている場合 production 環境向けにプリコンパイルしておきます。
bundle exec rake assets:precompile
Unicorn の動作確認
Unicorn のコンフィグファイルを作成し config/unicorn.rb などの名前をつけて保存します。ファイルのフォーマットは公式サイトを確認してください。
http://unicorn.bogomips.org/
http://unicorn.bogomips.org/examples/unicorn.conf.rb
参考までに、私の環境で使った設定はこんな感じ。
# coding:utf-8 # unicron.rb worker_processes 4 working_directory '/path/to/rails/app/' listen '/tmp/unicorn.sock', :backlog => 1 listen 4423, :tcp_nopush => true pid '/tmp/unicorn.pid' timeout 10 stdout_path '/path/to/rails/app/log/unicorn.stdout.log' stderr_path '/path/to/rails/app/log/unicorn.stderr.log' preload_app true GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true before_fork do |server, worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! old_pid = "#{server.config[:pid]}.oldbin" if old_pid != server.pid begin sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU Process.kill(sig, File.read(old_pid).to_i) rescue Errno::ENOENT, Errno::ESRCH end end sleep 1 end after_fork do |server, worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end
注意すべき点は working_directory を Rails アプリのドキュメントルートに変更することと listen するソケットの位置を自分の環境にあわせて変更する事と stdout_path, stderr_path を適当なディレクトリ(Rails.root/log 以下等)に書き換える事。後はサンプルがあちこちに載っているので、それらを参照すれば問題ないはずです。
次に production モード動作時の設定を変更します。config/environments/production.rb を編集します。
config.assets.compile = true # アセットパイプラインの設定 config.servre_static_assets = true # フロントは Nginx にするので、動作を確認したら false に戻す
ここまで完了したら Unicorn が動作するか確認します。
unicorn_rails -c config/unicorn.rb -E production -D
ブラウザを開いて、対象のサーバの IP にポート4423番でアクセスすると、アプリケーションの動作を確認できるはずです(できない時は /path/to/rails/app/log/production.log を見るとエラー内容が確認できます)。
bundle コマンドで unicorn をインストールしていると、ここで unicorn_rails コマンドが使えない可能性があります。その場合は gem install unicorn を改めて実行します。
コマンドが通ればサーバが動いているはずなので、適宜アクセスして確認して下さい。確認が終わったら、次のようにプロセスを探して停止します。
pgrep -f 'unicorn_rails master' kill -QUIT PID
Nginx インストール
インストールの前にユーザを追加します。
useradd nginx
また PCRE を使うので、それもインストールしておきましょう。
yum install pcre*
Nginx 本体はソースからインストールします。
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx make make install
インストールが完了したら prefix で指定したディレクトリの所有権を nginx ユーザに変更。
chown -R nginx:nginx /usr/local/nginx
ここで一旦 Nginx の起動テストを行います。Unicorn を80番ポートで動かしている場合、事前に停止してください。
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
この状態で対象マシンの IP を指定してブラウザからアクセスすると Nginx のデフォルト動作画面が表示されるはずです。確認が完了したら、サーバを一旦停止します。
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf -s stop
Nginx はソースからインストールしたので、起動時スクリプトへの追加は手動で行います。公式サイトからスクリプトのサンプルを拾ってきて、必要な箇所を書き換えて /etc/init.d/nginx に保存します。
http://wiki.nginx.org/RedHatNginxInitScript
対象のファイルに実行権限を付与して、起動時スクリプトの一覧に追加、起動時スクリプトをオンにします。
chmod +x /etc/init.d/nginx chkconfig --add nginx chkconfig nginx on
最後に Nginx のコンフィグファイルを設定して Unicorn と連携させます。Unicorn は80番以外のポートで起動させて UNIX ソケットで通信します。
/usr/local/nginx/conf/nginx.conf を開いて http ブロック内に upstream の設定を追記します。サーバには先ほど設定した Unicorn のソケットを指定しました。
upstream unicorn { server unix:/tmp/unicorn.sock; }
さらに server ブロック内にドキュメントルートの設定を追加します。ドキュメントルートは Rails アプリ内の public ディレクトリを指定して下さい。これにより、静的ファイルが Rails のルーティングを介さずに読み出せるようになります。
root /path/to/rails/root/public;
そして、上で設定した upstream へのプロキシ設定を行うため location ブロックを書き換えます。
location { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://unicorn; }
Rails3.1 を使っている場合 /assets 以下の静的ファイルを処理するよう記述します。(参考サイト)
location ~* ^/assets { expires max; add_header Cache-Control public; break; }
この状態で Nginx を再起動すれば、80番ポートから Rails アプリの動作を確認できるはずです。お疲れさまでした。