読者です 読者をやめる 読者になる 読者になる

ウォンツテック

技術的な話や会社設立に関わる話などを適当にしていきます

rails5 + puma + nginx で AWSテスト環境を構築してみる

puma

railsのAPサーバとWebサーバですが、昨今ではrails5にpumaが標準になったり、herokuがpumaを推奨したりとpumaがおすすめらしいので私のサービスのテスト環境もpumaで構築することとしました。

github.com


ざっくりとした手順は以下のような感じです

  1. railsの設定(ここは割愛します)
  2. puma.rbの編集
  3. puma起動ファイルの編集(/etc/init.d/puma)
  4. nginxのインストール&編集

ちなみに私のAWSubuntuで構築してます

pumaのコンフィグファイル修正

rails5でアプリを作るとアプリケーションがあるディレクトリのconfig/以下にpuma.rbってのが出来ています。
以下の項目を追記します

# アプリケーションがあるディレクトリと各種ファイルを生成するディレクトリを指定する
# tmpディレクトリは存在していないが、手動で作成するか起動時のスクリプトで作成するようにする
#  socketやlogやpidファイルを格納するディレクトリも存在していないので手動かスクリプトで作成
#  存在しないと起動出来ずに落ちます
app_dir = File.expand_path("../..", __FILE__)
tmp_dir = "#{app_dir}/tmp"

# 環境変数を指定する。起動時に変数があればそれを見る。無ければテスト環境である"staging"としている
rails_env = ENV['RAILS_ENV'] || "staging"
environment rails_env

# socketでbindする。nginxからsocket経由で接続するため
bind "unix://#{tmp_dir}/sockets/puma.sock"

# ログ出力ファイルの指定
stdout_redirect "#{tmp_dir}/logs/puma.stdout.log", "#{tmp_dir}/logs/puma.stderr.log", true

# pidとstateファイルの格納
pidfile "#{tmp_dir}/pids/puma.pid"
state_path "#{tmp_dir}/pids/puma.state"

pumaの起動ファイルの作成

pumaの起動ファイルについてはサーバが再起動しても自動で立ち上がるようにinit.dに書きます
upstartなどで書いてもいいいです

各種ディレクトリの生成(無ければ)と、起動ユーザーを気をつけて、起動時の環境変数に気をつけましょう

sudo vi /etc/init.d/puma

#!/bin/bash

NAME=puma
USER=ubuntu
APP_NAME=app
APP_DIR=/home/$USER/$APP_NAME
TMP_DIR=$APP_DIR/tmp
PID_DIR=$TMP_DIR/pids
SOCKET_DIR=$TMP_DIR/sockets
LOG_DIR=$TMP_DIR/logs
PUMA_BIN=/home/$USER/.rbenv/shims/puma

RAILS_ENV=staging

sudo -u $USER -H sh -c "mkdir -p $PID_DIR"
sudo -u $USER -H sh -c "mkdir -p $SOCKET_DIR"
sudo -u $USER -H sh -c "mkdir -p $LOG_DIR"

PIDFILE=$PID_DIR/puma.pid


start() {
  cd $APP_DIR;
  sudo -u $USER -H sh -c "echo \$\$ > $PIDFILE; RAILS_ENV=$RAILS_ENV $PUMA_BIN -C $APP_DIR/config/puma.rb -d"
}

stop() {
  echo -n "Stopping puma"
  kill -s SIGTERM `cat $PIDFILE`
}

restart() {
  stop
  start
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    restart
    ;;
  *)
    N=/etc/init.d/$NAME
    echo "Usage: $N {start|stop|restart}" >&2
    exit 1
    ;;
esac

これで sudo chmod +x /etc/init.d/puma をして sudo /etc/init.d/puma start でpumaを立ち上げてみましょう。

ps axu|grep pumaで

ubuntu   27220  0.0  1.6 343440 16468 ?        Sl   04:26   0:00 puma 3.7.0 (unix:///home/ubuntu/app/tmp/sockets/puma.sock) [app]
ubuntu   27227  0.1 10.3 830828 105096 ?       Sl   04:26   0:02 puma: cluster worker 0: 27220 [app]
ubuntu   27230  0.1 16.0 892820 162328 ?       Sl   04:26   0:02 puma: cluster worker 1: 27220 [app]

こんな感じで立ち上がっていなかったら失敗です。
tmp, sockets, pids, logsディレクトリが存在しているかと所有者やパーミションが起動ユーザーで問題ないか確認しましょう。

ちなみにですが、bundle.jsの生成など事前に各種ファイルのprecompileはしておきましょう。

nginxのインストールと設定

nginxのインストールは以下のサイトを参考にしました

How To Deploy a Rails App with Puma and Nginx on Ubuntu 14.04 | DigitalOcean

$ sudo apt-get install nginx

続いて設定ファイルの編集

$ sudo vi /etc/nginx/sites-available/default

/etc/nginx/sites-available以下にアプリ用のファイルを新規作成してsites-enabled以下にシンボリックリンクを張ってもよいです。

upstreamのところで先ほどpumaで生成したsocketに接続する設定をしています

upstream app {
    # Path to Unicorn SOCK file, as defined previously
    server unix:/home/ubuntu/app/tmp/sockets/puma.sock fail_timeout=0;
}

server {
    listen  80;
    server_name app.jp;
    keepalive_timeout 300;

    client_max_body_size 4G;

    root /home/ubuntu/app/public;

    try_files $uri/index.html $uri @app;

    location / {
          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://app;
          proxy_read_timeout 300s;
          proxy_send_timeout 300s;
    }

    # You can override error pages by redirecting the requests to a file in your
    # application's public folder, if you so desire:
    error_page 500 502 503 504 /500.html;
    location = /500.html {
            root /home/ubuntu/app/public;
    }
}

あとは sudo /etc/init.d/nginx start で起動し、上記のserver_nameで指定したドメイン(もしくはIP)に接続出来れば成功です。