Rails 5 + Unicorn + Nginx 環境構築メモ(自動起動設定も)


はじめに

Rail5勉強のための環境構築手順です。
AWS(EC2,RDS)で構築しました。冗長化はしてません。
Productionモードで、Unicorn/Nginxの起動ファイルまである参考サイトが意外と少ないですね。

Ruby

rbenvインストール

 $ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
 $ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
 $ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
 $ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
 $ source ~/.bash_profile
 $ rbenv --version

Ruby 2.3.2 インストール

 $ yum install -y gcc
 $ yum install -y openssl-devel readline-devel zlib-devel
 $ rbenv install -l
 $ rbenv install 2.3.2
 /tmp以下にログが履かれるのでtailで確認

Rails

Rails環境へ移動し、RubyのVerを指定

 $ cd /var/www/rails
 $ rbenv local 2.3.2
      RubyのVerファイルが生成される
 $ rbenv version

Bundlerインストール

 $ gem update --system
 $ rbenv exec gem install bundler
 $ rbenv rehash

Rails 5.0.0.1 インストール

 $ rbenv exec bundle init
  Gemfileが生成される
 $ vi Gemfile
  source "https://rubygems.org"
  gem "rails", "5.0.0.1"
 $ rbenv exec bundle install --path vendor/bundle
 $ rbenv exec bundle list

Rails プロジェクト初回設定

 $ rbenv exec bundle exec rails new homepage --skip-bundle -d mysql

 Rails をローカルインストールするために使用した Bundler 環境を削除
 $ rm -f Gemfile; rm -f Gemfile.lock; rm -rf .bundle; rm -rf vendor

Rails プロジェクトセットアップ

 $ cd homepage
 $ yum install mysql-devel
 $ rbenv exec bundle install --path vendor/bundle
 $ echo '/vendor/bundle' >> .gitignore

MySQL

 $ vi ./config/database.yml
    username: xxx
    password: <%= ENV['RAILS_DATABASE_PASSWORD'] %>
    host: xxx.xxx.rds.amazonaws.com
    database: homepage_production
    (本番環境想定なのでtest,developmentは消す)

 $ vi ~/.bash_profile
    export RAILS_ENV='production'
    export RAILS_DATABASE_PASSWORD='xxx'
 $ bundle exec rake db:create RAILS_ENV=production
 $ yum install nodejs --enablerepo=epel
 $ bundle exec rake db:migrate RAILS_ENV=production

Secret Key登録

 $ bundle exec rake secret
 $ vi ~/.bash_profile
    export SECRET_KEY_BASE='xxx'

起動確認

 $ bundle exec rails server -e production
 :3000で動作確認

Unicorn

インストール

 $ cd homepage
 $ vi Gemfile
    gem 'unicorn'
 $ rbenv exec bundle install --path vendor/bundle

Configファイル作成 ( ./config/unicorn.rb )

# -*- coding: utf-8 -*-
worker_processes 4

listen File.expand_path('tmp/unicorn.sock')
pid File.expand_path('tmp/unicorn.pid')

stderr_path File.expand_path('log/unicorn.log')
stdout_path File.expand_path('log/unicorn.log')

preload_app true

before_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill 'QUIT', Process.pid
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end

起動ファイル(/etc/init.d/unicorn)

#!/bin/bash
# chkconfig: 345 90 20
# description: Rails application
# processname: unicorn

RAILS_ENV=production
SERVICE=$RAILS_ENV

export HOME="/root"
source ~/.bashrc
source ~/.bash_profile

RAILS_ROOT_DIR="/var/www/rails/homepage"

PID=${RAILS_ROOT_DIR}/tmp/unicorn.pid
UNICORN_CONF=${RAILS_ROOT_DIR}/config/unicorn.rb

UNICORN_ALIVE=`ps aux|grep '${UNICORN_CONF}'|grep -v grep|wc -l`

start()
{
  if [ $UNICORN_ALIVE = 0 ]; then
    rm -f $PID
  fi
  if [ -e ${PID} ]; then
    echo "${SERVICE} already started"
    exit 1
  fi
  echo "start ${SERVICE}"
  source /etc/environment
  cd ${RAILS_ROOT_DIR}
  bundle exec unicorn_rails -c ${UNICORN_CONF} -E ${RAILS_ENV} -D
}

stop()
{
  if [ ! -e ${PID} ]; then
    echo "${SERVICE} not started"
    exit 1
  fi
  echo "stop ${SERVICE}"
  kill -QUIT `cat ${PID}`
}

force_stop()
{
  if [ ! -e ${PID} ]; then
    echo "${SERVICE} not started"
    exit 1
  fi
  echo "stop ${SERVICE}"
  kill -INT `cat ${PID}`
}

reload()
{
  if [ ! -e ${PID} ]; then
    echo "${SERVICE} not started"
    start
    exit 0
  fi
  echo "reload ${SERVICE}"
  kill -USR2 `cat ${PID}`
}

restart()
{
  if [ -e ${PID} ]; then
    stop
    sleep 3
  fi
  start
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  force-stop)
    force_stop
    ;;
  reload)
    reload
    ;;
  restart)
    restart
    ;;
  *)
    echo "Syntax Error: release [start|stop|force-stop|reload|restart]"
    ;;
esac
$ chmod 755 /etc/init.d/unicorn
$ chkconfig unicorn on
$ service unicorn start

Nginx

インストール

 $ yum install nginx
 $ cd /etc/nginx/conf.d/

Configファイル(/etc/nginx/conf.d/local.conf)

upstream unicorn {
  server unix:/var/www/rails/homepage/tmp/unicorn.sock;
}

server {
  listen 80;
  server_name   new.ishino.info;

  access_log /var/log/nginx/homepage_access.log;
  error_log /var/log/nginx/homepage_error.log;

  root /var/www/rails/homepage   ;

  client_max_body_size 100m;
  error_page 404 /404.html;
  error_page 500 502 503 504 /500.html;
  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    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;
  }
}
 $ chkconfig nginx on
 $ service nginx start