Nginx + Pumaで、Railsアプリケーションを表示しよう!

STEP16:Nginx + Pumaで、Railsアプリケーションを表示しよう! #Rails #Nginx


今回は、Amazon Linux(AMI)に、Nginxの設定を行って、独自ドメインにアクセスすると、Railsアプリケーションが表示されるように、設定を行います。

前回までで、AWSのEC2インスタンス(AMI)に、Nginxをインストール&起動をして、Nginxのトップ画面を表示させています。
また、Capistrano3を利用してローカル開発環境から、AMIにコマンドでデプロイが出来るところまで完了しています。

これから、独自ドメインにアクセスすると、Nginxの画面ではなく、Railsのトップ画面を表示できるようにします。
今回は、Amazon Linux(AMI)で起動させるWebサーバに「Puma」を利用したいと思います。
なので、全体的な構成は、「Nginx + Puma」となります。
Nginxのみだと静的なコンテンツ(htmlや、画像)を返すことはできますが、動的なコンテンツ(Rubyや、PHP)は、別途pumaのようなWebサーバが必要になります。

一般的というか有名なのは、Pumaより、「Phusion Passenger」とか「unicorn」らしいのですが、今回は、仕事でも利用している「Puma」を選択して勉強しながら構築していきたいと思います。
Pumaは、新しいリクエストをスレッドで立ち上げる完全な非同期アーキテクチャとのこと・・・深くはこれから勉強します^^

1.Puma起動スクリプトの設置

まず、Amazon Linux(AMI)にログインして、/etc/init.d/の配下に、起動スクリプトを作成します。
今回は、/etc/init.d/puma-pgnyumonとして、作成しました。
中身はこんな感じ。

#!/usr/bin/env bash
#
# puma - this script starts and stops the puma daemon
#
# chkconfig:   - 70 20
# description:  Puma is a Ruby web server.
# processname: puma

. /etc/rc.d/init.d/functions

APP_NAME=pgnyumon
APP_DIR=/var/www/${APP_NAME}/current
PUMA_SOCKET=/var/tmp/${APP_NAME}.sock
RUBY_PATH=/opt/rbenv/shims
ENVIRONMENT=production
PID_DIR=/var/tmp/pids
PUMA_PID_FILE=$PID_DIR/puma-${APP_NAME}.pid
SLEEP_TIME=1
AS_USER=${APP_NAME}

PATH=$RUBY_PATH:/usr/local/bin:$PATH

mkdir -p $PID_DIR

cd $APP_DIR

# check if puma process is running
puma_is_running() {
  if [ -S $PUMA_SOCKET ] ; then
    if [ -e $PUMA_PID_FILE ] ; then
      if cat $PUMA_PID_FILE | xargs ps -p > /dev/null ; then
        return 0
      elif cat $PUMA_PID_FILE | xargs pgrep -P > /dev/null ; then
        return 0
      else
        echo "No puma process found"
      fi
    else
      echo "No puma pid file found"
    fi
  else
    echo "No puma socket found"
  fi

  return 1
}

start_puma() {
  daemon --user $AS_USER bundle exec puma --daemon --environment $ENVIRONMENT --bind unix://$PUMA_SOCKET --pidfile $PUMA_PID_FILE
}

get_status() {
  status -p $PUMA_PID_FILE $APP_NAME
}


case "$1" in
  start)
    echo "Starting puma..."
    rm -f $PUMA_SOCKET
    start_puma
    echo "done"
    ;;

  stop)
    echo "Stopping puma..."
      kill -s SIGTERM `cat $PUMA_PID_FILE`
      rm -f $PUMA_PID_FILE
      rm -f $PUMA_SOCKET

    echo "done"
    ;;

  restart)
    if puma_is_running ; then
      echo "Hot-restarting puma..."
      kill -s SIGUSR2 `cat $PUMA_PID_FILE`

      echo "Doublechecking the process restart..."
      sleep $SLEEP_TIME
      if puma_is_running ; then
        echo "done"
        exit 0
      else
        echo "Puma restart failed :/"
      fi
    fi

    echo "Trying cold reboot"
    start_puma
    ;;

  status)
    get_status
    exit $?
    ;;

  *)
    echo "Usage: script/puma.sh {start|stop|restart}" >&2
    ;;
esac

下記の実行で起動します。

$ /etc/init.d/puma-pgnyumon start

停止は、こちら。

$ /etc/init.d/puma-pgnyumon stop

状態を確認するのは、こちら。

$ /etc/init.d/puma-pgnyumon status

2.Nginxに、仮想(バーチャル)ホストを設定

仮想ホストの設定ファイルを作成する前に、下記ディレクトリを作成します。

$ mkdir /etc/nginx/sites-available/
$ mkdir /etc/nginx/sites-enabled/

sites-availableの配下に、実体ファイルを作成して、sites-enabledの配下にはシンボリックリンクを作成します。
実体ファイルを作成します

$ vi /etc/nginx/sites-available/pgnyumon

中身は、こんな感じ。

upstream pgnyumon {
  server unix:///var/tmp/pgnyumon.sock;
}

server {
  listen <ポート番号>;
  server_name pgnyumon.com;
  root /var/www/pgnyumon/current;
  access_log /var/log/pgnyumon.access.log;
  error_log /var/log/pgnyumon.error.log;

  location / {
    proxy_pass http://pgnyumon;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

シンボリックリンクを作成します。

$ sudo ln -s /etc/nginx/sites-available/pgnyumon /etc/nginx/sites-enabled/pgyumon

作成した、/etc/nginx/sites-enabled/pgyumonを、/etc/nginx/nginx.confで、読み込む設定を追記します。

$ vi /etc/nginx/nginx.conf

下記の一行を追加して、sites-enablesのシンボリックリンクを読み込みます。

include /etc/nginx/sites-enabled/*;

Nginxの設定を反映します。

$ sudo nginx -s reload

Nginxの設定が終わったので、独自ドメインである、「http://pgnyumon.com」にブラウザからアクセスしてみます。
そうすると、真っ白な画面に、下記のエラーメッセージが出力されました。

An unhandled lowlevel error occurred. The application logs may have details.

Amazon Linux(AMI)にログインして、試しに、rails serverで起動して、wget http://localhost:3000とかでアクセスしてみると、500のInternal Server Errorが発生して、下記エラーが出ていました。

Rack app error: #<RuntimeError: Missing `secret_token` and `secret_key_base` for 'production' environment, set these values in `config/secrets.yml`>

どうやら、production環境に、secret_key_baseを設定する必要があるようです。
開発環境に戻って、config/secrets.ymlのproductionを開きます。

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

developとtest環境には、長いkeyが設定されていますが、productionには未設定です。
なので、下記コマンドで、ランダムな文字列を生成して、secret_key_baseに設定します。

bundle exec rake secret

生成された文字列を、config/secrets.ymlのproduction:secret_key_baseに設定します。
Gitにコミット、GitHubにpush、Capistranoで、productionにデプロイします。
Amazon Linux(AMI)にログインして、環境変数を設定します。

$ export SECRET_KEY_BASE=<設定したsecret_key_base>

念のため、Puma再起動

$ /etc/init.d/puma-pgnyumon restart

あらためて、独自ドメインの、http://pgnyumon.comにアクセスすると、こんな画面が表示されました。
スクリーンショット 2015-10-04 22.10.56
メッセージはこんな感じ。

The page you were looking for doesn't exist.

You may have mistyped the address or the page may have moved.

Googleで検索してみると、このエラーは、まだRailsアプリケーションが、デフォルトで何も入っていない状態の場合に出力されるようです。
なるほど・・・確かに、Railsプロジェクトを作成しただけで何も作ってない・・・。
でも、Nginx + Pumaで、Railsアプリケーションの表示を設定するところは、ひとまず出来たようです。

と言うことで、今回はここまで!
次回以降に、Railsでコンテンツを開発していって、どんどんAWSの構築も進めていきたいと思います。

前回の記事は、「Rails4+Capistrano3+pumaで、自動デプロイをしよう!」

Ruby on Railsおすすめ書籍

Ruby on Railsの勉強で参考になった書籍です!

Ruby on Railsで質問したい!

Teratail(テラテイル)

WEBエンジニア専用のQ&Aサイトで、RubyやRailsも質問することができます。活発に質問と回答がされていますので、会員登録をして利用してみると良いと思います(^o^)。

エンジニアのためのQ&Aサイト【teratail】

Ruby on Railsが学べるオンラインスクール

好きな場所で好きな時間に受講できるオンラインスクール!最近は、Ruby on Railsも学ぶことができます!

TechAcademy(テックアカデミー)

オンラインでの週2回マンツーマンでのメンタリング、毎日15〜23時のチャット・レビューサポートで短期間で未経験からオリジナルサービスを開発できるようになる学習プログラム。オリジナルサービスをHerokuを使って公開するところまでを行います。

オンラインブートキャンプ Webアプリケーションコース