Ruby
AWS
EC2
RubyOnRails
DynamoDB

DBなしのRails5アプリを最短でAmazon EC2上に構築して公開する

データベースにAmazon DynamoDBを使ったRailsアプリを作りたいと思い、とりあえずDBなしのRailsアプリを最短でEC2で公開するにはどうしたらいいかをやってみました。

前提

下準備

下記の記事が非常に分かりやすかったです。

(下準備編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで
↑これは全て完了させます。

(DB・サーバー構築編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで
↑ここではDBは使わないので、「8.EC2インスタンスの作成」から最後までを完了させます。

ユーザー作成

(デプロイ編①)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで
↑この記事の「8.EC2へのログイン」まで終わらせる。

nginxのインストールと起動テスト

一度、この時点でnginxのインストールと起動を行い、ブラウザからアクセスしてデフォルトのページが表示されるかどうかを確認します。

最初からインストールされている全パッケージのアップデート

$ sudo yum update

nginxのインストール

$ sudo yum install nginx
$ nginx -v

nginxの起動

$ sudo service nginx start

起動後、EC2インスタンスのパブリックDNS or 割り当てたElastic IPにブラウザからアクセスして、下記のページが表示されることを確認します。

スクリーンショット 2017-12-29 16.36.03.png

環境構築

必要なもののインストール

$ sudo yum install make patch git gcc openssl-devel gcc-c++  epel-release
  • make: makeコマンド
  • patch: patchコマンド
  • git: gitコマンド(gitからクローンしたりするために必要)
  • gcc: Rubyをインストールするために必要
  • openssl-devel:Rubyをインストールために必要
  • gcc-c++: Nodeモジュールのコンパイルに必要
  • epel-release: Node.jsをyumでインストールするために必要

その他、依存関係にあるライブラリを入れていきます。

$ sudo yum install libyaml-devel libffi-devel libicu-devel
$ sudo yum install libxml2 libxslt libxml2-devel libxslt-devel
$ sudo yum install zlib zlib-devel readline readline-devel
$ sudo yum install ruby-devel

Node.jsとyarn、nのインストールとNode.jsの最新版へのアップデート

$ sudo yum install nodejs npm --enablerepo=epel 
$ sudo npm install -g yarn
$ sudo npm install -g n
$ sudo n latest

rbenvのインストール

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

ruby-buildのインストール

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

インストールできるrubyのバージョン一覧を確認

$ rbenv install -l

rubyをインストール

$ rbenv install -v 2.5.0
$ rbenv global 2.5.0
$ source .bash_profile
$ ruby -v

bundlerとrakeのインストール

$ sudo gem update --system
$ sudo gem install bundler
$ sudo gem install rake

railsのインストール

$ gem install rails -N
$ rbenv rehash
$ rails -v

Railsアプリの新規作成

アプリは/var/www/に作成します。wwwディレクトリを作る過程で、varディレクトリとwwwディレクトリの所有者を自分のユーザーに設定します。
DBなしのRailsアプリを作るため、-O オプションをつけてrails newします。
最後に、rakeでアセットをプリコンパイルしておきます。

[ユーザー名@ip~~~]$ cd /
[ユーザー名@ip~~~ /]$ sudo chown ユーザー名 var
[ユーザー名@ip~~~ /]$ cd var
[ユーザー名@ip~~~ var]$ sudo mkdir www
[ユーザー名@ip~~~ var]$ sudo chown ユーザー名 www
[ユーザー名@ip~~~ var ]$ cd www
[ユーザー名@ip~~~ www]$ rails new myapp -O
[ユーザー名@ip~~~ www]$ cd myapp
[ユーザー名@ip~~~ myapp]$ rake assets:precompile RAILS_ENV=production

$ lsコマンドを打った時に自分のアプリ名(myapp)というフォルダができていれば成功です。

UNICORNのインストールと設定

Gemfileに下記を追加

group :production, :staging do
    gem 'unicorn'
end

そしてbundle installを実行

アプリのディレクトリのconfigディレクトリの中にunicorn.rbというファイルを作成します。

[ユーザー名@ip~~~ myapp]$ cd config
[ユーザー名@ip~~~ config]$ vi unicorn.rb

下記をコピペします。コピペしたらShift + ZZで閉じます。

config/unicorn.rb
  # set lets
  $worker  = 2
  $timeout = 30
  $app_dir = "/var/www/myappp" #自分のアプリケーション名
  $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
  worker_processes  $worker
  working_directory $app_dir
  stderr_path $std_log
  stdout_path $std_log
  timeout $timeout
  listen  $listen
  pid $pid
  # loading booster
  preload_app true
  # 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

(viコマンドの操作についてはこちら

ngnixの設定

nginxの設定ファイルを編集します。nginxの設定ファイルは/etc/nginxの中にあるnginx.confです。

[ユーザー名@ip~~~ config]$ cd ~
[ユーザー名@ip~~~ ~]$ sudo vi /etc/nginx/nginx.conf

このファイルの中にinclude conf/mime.types;という記述があるので、その下にinclude /etc/nginx/conf.d/myapp.conf;を追記(セミコロンを忘れない!)

そしてmyapp.confは下記をコピペします。myappのところは自分のアプリ名に編集して下さい。

/etc/nginx/conf.d/myapp.conf
# log directory
error_log  /var/www/myapp/log/nginx.error.log;
access_log /var/www/myapp/log/nginx.access.log;
# max body size
client_max_body_size 2G;
upstream app_server {
  # for UNIX domain socket setups
  server unix:/var/www/myapp/tmp/sockets/.unicorn.sock fail_timeout=0;
}
server {
  listen 80;
  server_name あなたのEC2インスタンスのElastic IP;
  # nginx so increasing this is generally safe...
  keepalive_timeout 5;
  # path for static files
  root /var/www/myapp/public;
  # page cache loading
  try_files $uri/index.html $uri.html $uri @app;
  location @app {
    # HTTP headers
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }
  # Rails error pages
  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /var/www/myapp/public;
  }
}

ここまで完了したら、一度nginxを再起動してみましょう。

$ sudo service nginx stop
$ sudo service nginx start

スクリーンショット 2017-12-29 17.43.38.png

パブリックDNS or EC2インスタンスのElastic IPにアクセスしてこの画面になれば、設定がちゃんとできています。
(nginxが起動していて、unicornが起動できていない時の画面)

シークレットキーを設定してunicornを起動

アプリがあるディレクトリで下記のコマンドを打ってシークレットキーを設定&unicornを起動させます。

[ユーザー名@ip~~~ myapp]$ export SECRET_KEY_BASE=`rake secret`
[ユーザー名@ip~~~ myapp]$ unicorn_rails -E production -c config/unicorn.rb -D

スクリーンショット 2017-12-29 19.31.59.png

パブリックDNS or EC2インスタンスのElastic IPにアクセスして↑の画面になれば、unicornは起動できています。

なお、unicornが起動しているかどうかは ps -ef | grep unicorn | grep -v grepコマンドを打って確認します。3行ほど何か表示されれば起動していて、何も表示されなければ起動していません。

unicornの停止はアプリのあるディレクトリで下記のコマンドを打ちます。

[ユーザー名@ip~~~ myapp]$ sudo kill -QUIT `cat tmp/pids/unicorn.pid`

unicornを再び起動する時には、再びシークレットキーの設定が必要です。

トップページを作る

今のままではページが1ページも作られていないので、"The page you were looking for doesn't exit."と表示されています。railsコマンドで適当にトップページを作り、ルーティングを設定してみます。ここではhomeというコントローラのtopアクションを作ります。

[ユーザー名@ip~~~ myapp]$ rails generate controller home top

次に、routes.rbを編集してルーティングを設定します。ルート”/”へのgetリクエストに対して、'home#top'を呼び出すようにします。

[ユーザー名@ip~~~ myapp]$ cd config
[ユーザー名@ip~~~ myapp]$ vi routes.rb

そして下記のように書き換えます。

myapp/config/routes.rb
Rails.application.routes.draw do
  get '/' => 'home#top'

  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

ここまで編集したら、一度unicornを再起動します。アプリのあるディレクトリで下記のコマンドを打ちます。

[ユーザー名@ip~~~ myapp]$ sudo kill -QUIT `cat tmp/pids/unicorn.pid`
[ユーザー名@ip~~~ myapp]$ export SECRET_KEY_BASE=`rake secret`
[ユーザー名@ip~~~ myapp]$ unicorn_rails -E production -c config/unicorn.rb -D

そしてパブリックDNS or EC2インスタンスのElastic IPにアクセスして、下記の画面になれば成功です。

スクリーンショット 2017-12-29 19.40.49.png

参考

ec2(amazon linux)にnginxを導入(デフォルトページの表示まで)
(デプロイ編②)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで
Rails4 & Unicorn & Nginx & EC2でサーバー構築
AWSのEC2上でRails+Unicorn+Nginxを実現する
Amazon LinuxにRuby on Rails環境構築(rbenv + ruby-build + Ruby 2.2.1 + Rails 4.2.1インストール)