Rails
nginx
AWS
PostgreSQL
unicorn

Nginx + Unicorn + Rails + PostgreSQLでサーバー構築


前提条件


  • AWS上で既にEC2やRDSが立ててあり、ネットワーク設定等が済んでいる状態を想定。

  • 各ミドルウェアは2018年6月現在の最新安定板のバージョンを利用。


Ruby + Railsのインストールと設定


1. 環境構築に必要なパッケージをインストール

$ sudo yum -y install git gcc gcc-c++ make zlib-devel httpd-devel openssl-devel curl-devel readline-devel


yumとは


  • Yellowdog Updater Modified

  • パッケージ管理システムのこと

  • yumはrpmを統合管理している(rpmをラップしている)


パッケージの概要


  • git : git

  • gcc gcc-c++ : C言語やC++などのコンパイラ

  • make : コンパイル型プログラムビのビルダー

  • zlib : データの圧縮や伸張を行うライブラリ

  • ssl : SSL/TLC(暗号化通信プロトコル)のライブラリ

  • curl : 色々なプロトコルに対応したデータ転送ライブラリ

  • readline : 行頭・行末移動やヒストリ機能などを提供するライブラリ


無印とdevelとの違い



  • -develはを示し、ヘッダファイルが含まれている。

  • これがないと、ソースコードからアプリケーションをインストールしたいときにヘッダファイルが見つからず困ることがある。

  • 詳しくはこちらの記事を参考。


2. rbenvをインストール

$ git clone git://github.com/sstephenson/rbenv.git ~/.rbenv


rbenvとは


  • Simple Ruby Version Management

  • rvmをよりシンプルにしたRubyのバージョン管理ができるライブラリ


3. PATHに追加

$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile


4. .bash_profileに追加

$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile


5. .bashrcの再読み込み

$ source ~/.bashrc


6. シェルをログインシェルから起動させる

$ exec $SHELL -l


7. ruby-buildをインストール

$ sudo git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

$ cd ruby-build

$ sudo ./install.sh


ruby-buildとは


  • ruby-buildは、UNIX系のシステム上で異なるバージョンのRubyをコンパイルしインストールするための、 rbenv installコマンドを提供するrbenvのプラグイン

  • install.shを叩き、ruby-buildを最新にしている


8. rubyをインストール可能かどうか確認

$ rbenv install --list | grep 2.5.1


9. バージョンを指定してインストール

$ rbenv install 2.5.1


10. rbevの再読み込み

$ rbenv rehash


11. 使用するrubyを指定

$ rbenv global 2.5.1;rbenv rehash


指定方法について


  • global : システム全体で使用するバージョンを指定

  • local : 特定のディレクトリでバージョンを使用する場合に指定


    • そのディレクトリにある.ruby-versionファイルを書き換えて管理している




12. インストールしたrubyのバージョンを確認

$ ruby -v


13. bundlerのインストール

$ gem install bundler;rbenv rehash


bundlerとは


  • 前提として、gemというRubyのライブラリがある


    • (例)rails, sinatra, unicorn, Rspec・・・



  • bundlerとは、gemを個別にインストールできるgemのライブラリ

  • 詳しくはBundlerの使い方を参照。


14. railsのインストール

$ gem install rails;rbenv rehash


15. railsのバージョンを確認

$ rails -v


railsのバージョンを変更したい時

$ gem uninstall railties -v '5.2.0'で最新版のrailsを削除後、バージョンを指定してインストール

$ gem i -v 5.1.4 rails;rbenv rehash


16.SQLiteのインストール(不要な場合は飛ばしてOK)

$ sudo yum -y install sqlite-devel

$ gem install sqlite3;rbenv rehash


17. Railsアプリを/var/www/配下に作成

※ 今回DBはpostgresqlを利用するため、rails new時に指定しておく。

$ sudo chown ec2-user /var

$ cd /var

$ sudo chown ec2-user www

$ cd /var/www/

$ rails new myapp2 -d postgresql


18. JavaScript Runtimeを有効にする

$ vi /var/www/myapp/Gemfile

gem 'therubyracer', :platforms => :rubyを追加


19. unicornのgemをインストール

$ vi /var/www/myapp/Gemfile

gem 'unicorn'を追加。


20. Gemfileを更新したのでbundleをインストール

$ cd myapp

$ bundle install


21. railsアプリを確認

$ rails server


22. 別タブを開き、curlする

$ curl -I localhost:3000

以下のように、200番が帰って来ればOK

HTTP/1.1 200 OK


Unicorn + Nginx のインストールと設定


1. Unicornのインストール

$ gem install unicorn;rbenv rehash


2. configファイル作成

$ vi myapp/config/unicorn.conf

次のように修正する。

参考

- Unicorn設定のまとめ


/var/www/myapp/config/unicorn.conf

# set lets

$worker = 2
$timeout = 30
$app_dir = "/var/www/myapp"
$listen = File.expand_path 'tmp/sockets/unicorn.sock', $app_dir
$pid = File.expand_path 'tmp/pids/unicorn.pid', $app_dir
$std_log = File.expand_path 'log/unicorn.log', $app_dir

# set config
## Unicornは複数のワーカーで起動するのでワーカー数を定義
## サーバーのメモリなどによって変更すること。
worker_processes $worker

## Unicornの起動コマンドを実行するディレクトリを指定
working_directory $app_dir

## Unicornのエラーログと通常ログの位置を指定
stdout_path $std_log
stderr_path $std_log

## 接続タイムアウト時間
timeout $timeout

## Nginxでのlisten指定 unicornを呼ぶ
listen '/var/www/myapp/tmp/sockets/unicorn.sock'

## プロセスの停止等に必要なpidファイルの保存先を指定
pid $pid

## loading booster : Unicornの再起動時にダウンタイムなしで再起動が行われる
preload_app true

## before starting processes
## - $ kill -USR2 `cat /path/to/unicorn.pid` のようなUSR2で再起動をかける時に、新プロセスを立ち上げて旧プロセスを停止する
## before starting processes
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
Process.kill "QUIT", File.read(old_pid).to_i
rescue Errno::ENOENT, Errno::ESRCH
end
end
end
# after finishing processes
after_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end



3. nginxインストール

$ sudo yum install nginx

※ Amazone Linux2の場合は、以下の操作

$ amazon-linux-extras | grep nginx

$ sudo amazon-linux-extras install nginx1.12


4. nginxの起動確認

$ sudo /etc/init.d/nginx start

$ ps -ax | grep nginxでプロセスを確認するか、EC2のパブリックDNSでの確認する。

※ Amazone Linux2の場合は、以下の操作

$ sudo systemctl start nginx.service


5. nginxを停止

$ sudo /etc/init.d/nginx stop

※ Amazone Linux2の場合は、以下の操作

$ sudo systemctl stop nginx.service


6. nginxの設定ファイル編集

参考

$ sudo vi /etc/nginx/nginx.conf


/etc/nginx/nginx.conf

# For more information on configuration, see:

# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/

# nginxを起動するとmaster processとworker process、cache manager processの三つのプロセスが起動します。
# その中のmaster process以外を起動するユーザーを指定します。
# master processはrootユーザーで起動
user nginx;

# コア数よりも多くの値を指定しても問題がない
# - autoに指定するとコア数を設定してくれる
# - コア数は以下のコマンドで調べれる
# - $ grep processor /proc/cpuinfo |wc
worker_processes auto;

# エラーログを格納するファイルの指定
error_log /var/log/nginx/error.log;

# pidを格納するファイルの指定
pid /var/run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

# eventモジュールの指定
events {
# 1つのワーカーが同時に処理できる接続数
worker_connections 1024;
}

# webサーバーとして使用するメインとなる処理
http {
# ログのフォーマットを定義
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

# 上記で指定したlog_formatを最後に指定
# - この定義はserverブロックなどでも使用できる
access_log /var/log/nginx/myapp_access.log main;
# error_logにフォーマットはしてきでないの注意
error_log /var/log/nginx/myapp_error.log;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;

# MIMEタイプと拡張子の関連付けを定義したファイルを読み込み
include /etc/nginx/mime.types;
# 上述のmime.typesで拡張子からMIMEタイプを決定できなかったときに、ここで指定したMIMEタイプが適応される
default_type application/octet-stream;

# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.

upstream unicornapp {
server unix:/var/www/rails/coq-api/tmp/sockets/unicorn.sock;
}
# nginxでバーチャルホストの運用をする際に利用する
# - httpブロック内に記述
server {
# IPアドレスまたはポート番号を指定
listen 80;
server_name localhost;

# 指定のロケーション(パスやファイル)の場合にのみ適用される
location / {
proxy_pass http://unicornapp;
}
}
}



7. nginx起動

$ sudo /etc/init.d/nginx start

※ Amazone Linux2の場合は、以下の操作

$ sudo systemctl start nginx.service


8. unicorn起動

$ cd var/www/myapp

$ unicorn -c config/unicorn.conf -D

※ unicornを停止するときはmasterプロセスをkillする

$ ps ax|grep unicorn|grep -v grep

$ kill ****


9. 動作確認

EC2のパブリックDNSで確認してみる。

スクリーンショット 2018-06-30 16.19.39.png


PostgreSQLのインストールと設定

※ RDSの設定に関して、postgresqlのwell knouwn portは5432なので注意する。


1. PostgreSQLのインストール

こちらのページを参考に、Amazon Linux AMIに対応しているPSQLのrpmをインストールする。

$ sudo yum localinstall -y https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-ami201503-96-9.6-2.noarch.rpm

$ sudo yum install -y postgresql96 postgresql96-server postgresql96-libs postgresql96-contrib postgresql96-devel


2. バージョンを確認

$ psql --version


3. gemのインストール

$ vi /var/www/myapp/Gemfile

Gemifileにgem 'pg'を追加。

$ gem install pg;rbenv rehash

$ cd myapp

$ bundle install


4. database.ymlの修正

postgresqlを利用するように修正する。

参考 : http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html


/var/www/myapp/config/database.yml

default: &default

adapter: postgresql
encoding: utf8
pool: 5
username: [user] # RDS側で設定したユーザーを指定
password: [pass] # RDS側で設定したパスを指定
host: [****.rds.amazonaws.com] # RDSのエンドポイントを指定
timeout: 5000

development:
<<: *default
database: my_development # RDS側で作成したDBを指定

test:
<<: *default
database: my_test # RDS側で作成したDBを指定

production:
<<: *default
database: my_production # RDS側で作成したDBを指定



5. EC2 → RDSの接続確認

AWS側で正しく設定ができているか確認する。

$ psql -h [RDSのエンドポイント] -U [RDSのUsername] -d [RDSのDB NAME] で接続確認

$ psql -l で作成したDBが確認できれば接続確認OK。

psqlコマンドについてはPostgreSQLの基本的なコマンドを参考。

※ localで開発するような場合はこちらが参考になりそう。


5-1. エラー対応


DB実行時の環境を環境変数に自動設定する


config.eager_load = trueのとき


pgのgemが無い

バージョンを落とすことで解決することがある。


  • Gemファイルに gem 'pg', '< 0.21.0' を追記

  • $ gem install pg

  • $ bundle install


6. Rails -> RDSでの動作確認

試しに、名前と年齢を持つUserモデルを作成してみる。


6-1. scaffoldの実行

自動でModel, Controller, Viewの雛形が作成される。

$ rails generate scaffold user name:string age:integer


6-2. migrateの実行

マイグレーションファイルを利用してDBにテーブルを作成する。

$ rake db:migrate

最後に、作成したテーブルを確認する。

$ psql -h [RDSのエンドポイント] -U [RDSのUsername] -d [RDSのDB NAME] で接続

myRDS=> \c myRDS でDBを選択

myRDS=> \dt; でテーブルを確認

myRDS=> select * from users; で中身を見て、以下のようになっていれば成功。

 id | name | age | created_at | updated_at 

----+------+-----+------------+------------
(0 行)

※ 画面アクセス時にMigrations are pendingと怒られた時は、uniconとrailsを再起動すれば解決すると思います。

おわり。