RailsをUnicorn・Nginxで起動する



今回はRuby on RailsをUnicorn・Nginxで起動するまでの設定です。ほとんどがこのページ( http://www.virment.com/ubuntu-nginx-unicorn-rails/ )のパクリです、本当に参考になりました。僕のページより詳しく見やすいので、皆さんそちらを見てください。僕のページでは上手くいかなかった点のメモになります。


/etc/nginx/nginx.confの修正(ほとんど変更しない)
  • $ sudo vi /etc/nginx/nginx.conf

user www-data;
worker_processes 4;
pid /run/nginx.pid;
events {
    worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;

include /etc/nginx/mime.types;
default_type application/octet-stream;

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

gzip on;
gzip_disable "msie6";
gzip_proxied any;
gzip_http_version 1.1;
gzip_min_length 500;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

upstream unicorn {
 server unix:/var/www/practice/tmp/unicorn.sock fail_timeout=0;
}
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
自分で追加するのはupstream unicornの部分。自分のアプリケーションのパスを入れる。


/etc/nginx/sites-available/defaultを書き換える(不安な人は別のディレクトリにコピーをとっておく)
プロジェクトがどこ(/var/www/)にあるか、などの情報を書く。
  • $ sudo vi /etc/nginx/sites-available/default

server {
listen 80;
root /var/www/practice;
index index.html index.htm;

keepalive_timeout 300;
client_max_body_size 4G;

server_name raspberrypi 192.168.0.10;  #自分の設定を入れてください。

location /practice/ {
try_files $uri/index.html $uri.html $uri @unicorn;
}
location ~ ^/assets/(.*) {
alias /var/www/practice/public/assets/$1;
}
location / {
proxy_set_header Host $http_host;
proxy_pass http://unicorn;
}
location @unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded_Proto $scheme;
proxy_redirect off;

proxy_pass http://unicorn;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
error_page 500 502 503 504 /500.html;
location = /500.html {
root /var/www/practice/public;
}
}
個別に設定しなければならないのが、rootとservername。rootには/var/www/practiceの様に自分のプロジェクトの置いてあるディレクトリのパスを記述する。全ての設定がうまくいけば、http://raspberrypi.localもしくはhttp://192.168.0.10でアプリケーションにアクセスできる。

  • $ sudo service nginx reload      (再読み込みし)
  • $ sudo service nginx start        (起動させる)


Unicornのサービス登録
この設定を行うと$ sudo service unicorn startといったコマンドが使えるようになる
  • $ sudo vi /etc/init.d/unicorn     (新規ファイル)

#!/bin/sh

### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the unicorn web server
# Description: starts unicorn
### END INIT INFO

USER=userneme   #piとかラズベリーパイのsudoユーザー名
APP_ROOT=/var/www/practice
RAILS_ENV=production           #test,developmentなど
PID=$APP_ROOT/tmp/unicorn.pid
DESC="Unicorn app - $RAILS_ENV"

RBENV_RUBY_VERSION=`cat $APP_ROOT/.ruby-version`
RBENV_ROOT="/home/$USER/.rbenv"
PATH="$RBENV_ROOT/bin:$PATH"
SET_PATH="cd $APP_ROOT $$ rbenv rehash && rbenv local $RBENV_RUBY_VERSION"
UNICORN="bundle exec unicorn"

UNICORN_OPTS="-c $APP_ROOT/config/unicorn.rb -E $RAILS_ENV -D"
CMD="$SET_PATH && $UNICORN $UNICORN_OPTS"
TIMEOUT=60
action="$1"
set -u

old_pid="$PID.oldbin"
cd $APP_ROOT || exit 1
sig () {
test -s "$PID" && kill -$1 `cat $PID`
}
oldsig () {
test -s $old_pid && kill -$1 `cat $old_pid`
}

case $action in
start)
sig 0 && echo >&2 "$DESC is already running" && exit 0
su - $USER -c "$CMD"
;;
stop)
sig QUIT && echo "Stopping $DESC" exit 0
echo >&2 "Not running"
;;
force-stop)
sig TERM && echo "Force-stopping $DESC" && exit 0
echo >&2 "Not running"
;;
restart)
sig QUIT && echo "Restarting $DESC" && sleep 2 \
&& su - $USER -c "$CMD" && exit 0
;;
reload)
sig HUP && echo "Reloading configuration for $DESC" && exit 0
echo >&2 "Couldn't reload configuration."
;;
upgrade)
if sig USR2 && echo "Upgrading $DESC" && sleep 10 \
&& sig 0 && oldsig QUIT
then
n=$TIMEOUT
while test -s $old_pid && test $n -ge 0
do
printf '.' && sleep 1 && n=$(( $n - 1 ))
done
echo

if test $n -lt 0 && test -s $old_pid
then
echo >&2 "$old_pid still exists after $TIMEOUT seconds"
exit 1
fi
exit 0
fi
echo >&2 "Couldn't upgrade, starting 'su - $USER -c \"$CMD\"' instead"
su - $USER -c "$CMD"
;;
status)
sig 0 && echo >$2 "DESC is running." && exit 0
echo >&2 "DESC is not running."
;;
reopen-logs)
sig USR1
;;
*)
echo >&2 "Usage: $0 <start|stop|restart|reload|upgrade|force-stop|reopen-logs>"
exit 1
;;
esac


RUBYのバージョンを記述する。僕の場合は2.2.1とだけ
  • $ vi /var/www/practice/.ruby-version     (新規ファイル、前のファイルにここを読む記述がしてある)
  • $ sudo chmod +x /etc/init.d/unicorn    (実行属性をONにする)
  • $ sudo update-rc.d unicorn defaults     (defaultを指定。サービス起動用リンクを作成)

※ ### BIGINの記述を間違えると「missing LSB tags and overrides」というエラーになる。


Unicorn設定ファイルの作成(ユニコーンの動作の設定)
  • $ vi /var/www/practice/config/unicorn.rb   (新規ファイル)

app_path = File.expand_path(File.dirname(__FILE__) + '/..')

worker_processes 2
listen app_path + '/tmp/unicorn.sock', backlog: 64
timeout 300
working_directory app_path
pid app_path + '/tmp/unicorn.pid'
stderr_path app_path + '/log/unicorn.log'
stdout_path app_path + '/log/unicorn.log'

preload_app true

GC.respond_to?(:copy_on_write_friendly=) &&
GC.copy_on_write_friendly = true

before_fork do |server, worker|
defined?(ActiveRecord::Base) &&
ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
defined?(ActiveRecord::Base) &&
ActiveRecord::Base.establish_connection
end

※unicorn.rbとinit.d/unicornのpidの指定は同じ宛先にする



UnicornとNginxの起動、停止
  • $ sudo service nginx start
  • $ sudo service nginx stop
  • $ sudo service nginx restart

  • $ sudo service unicorn start
  • $ sudo service unicorn stop
  • $ sudo service unicorn restart


問題解決
ここまでやってきましたが、未だに僕はうまくいっていません笑
色々調べてみて、本番環境でうまくいっていないということがわかったので、サーバーサイドの勉強は休止したいと思います。他にも悩んでいる方もいると思うので、問題の切り分けの方法を残したいと思います。

まずスペルミスの確認
自分では完璧のつもりが結構あります。しかも、エラーの直接の原因でない事も多い。

rbenvのインストール場所、ディレクトリのパーミッション
一番僕がハマったのはここでした。RBENV_ROOTでは"/home/$USER/.rbenv"を指定しているので、別の場所にインストールした人は注意です。また、Nginxはwww-dataが実行しているので、user権限要のディレクトリを実行する動作が伴う場合には失敗してしまいます(/var/wwwでrails newが出来ないのと同じ理由)。

sudo service unicorn コマンドがうまくいかない

Job for unicorn.service failed.となるとき。

  • $ sudo systemctl status unicorn.service
を見るとどこで失敗したかがわかるのでそこを修正する。
※因みに僕は、.ruby-versionファイルを作り忘れて、「そのようなファイルはありません」と怒られていた。


画面に何も表示されない
unicornの起動時に先ほどの様なエラーは確認できなかったので、unicornとnginx間は問題なかったと仮定して、Unicorn.logを確認する。
  • $ vi /var/www/practice/log/unicorn.log
「Missing `secret_key_base`for・・・・・」となっていたら環境変数が設定されていないことが原因です。

  • $ bundle exec rake secret
  • $ export SECRET_KEY_BASE=`bundle exec rake secret`
  • $ sudo service unicorn restart
で改善します。config/secret.ymlに値が入るのかな?
dotenv-railsを使うと便利みたいですが、まだ試していません。※git時には注意


We're sorry, but something went wrong.
If you are the application owner check the logs for more information.

スクリーンショット 2015-12-13 22.27.45.png

404エラーと呼ぶらしいですね、僕もここから先に進めていない。しかし、この画面が出ているということはRailsのエラー画面には到達できているので、nginxとunicornの設定は出来たと喜んでもいいのかもしれません。

では、問題の切り分けから。この画面が出るという事は、本番モードで起動しているという事。スクリーンショット 2015-12-14 3.21.54.png

まず、WEBrickで表示できるのかどうか
  • $ bundle exec rails s -b 0.0.0.0   (オプション付きのため、作業PCからでも確認できる)
ブラウザにてhttp://192.168.0.10にアクセスし確認する→問題ない。

WEBrick本番モードでどうか
  • $ bundle exec rails s -e production -b 0.0.0.0   (本番モードで起動)
→問題ない。

Unicorn開発モードでどうか
  • $ sudo service unicorn stop
  • $ sudo vi /etc/init.d/unicorn
  • RAILS_ENV=development に変更する(開発環境で起動する設定に変更)
  • $ sudo systemctl daemon-reload   (init.dの設定変更の読み込み)
  • $ sudo service unicorn start
→問題ない

Unicorn起動コマンド直打でどうか
  • $ unicorn_rails -c config/unicorn.rb -E production -D
→問題ない

このブログを書いている最中、今なぜか動く様になってしまいました笑
この後検証が必要ですが、他にやった事とするとアセットのプリコンパイルか/tmp/unicorn.sockの削除ぐらいです。なぜ動く様になったのだろうか。一週間くらいUnicorn・nginxと格闘してきたが、これでRailsの勉強に戻れる。

この記事へのコメント