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

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

#前提
##下準備
下記の記事が非常に分かりやすかったです。

[(下準備編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで](https://qiita.com/naoki_mochizuki/items/f795fe3e661a3349a7ce)
↑これは全て完了させます。

[(DB・サーバー構築編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで](https://qiita.com/naoki_mochizuki/items/22cfbf4bf7ec95f6ac1c#8ec2%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%AE%E4%BD%9C%E6%88%90)
↑ここではDBは使わないので、「8.EC2インスタンスの作成」から最後までを完了させます。

##ユーザー作成
[(デプロイ編①)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで](https://qiita.com/naoki_mochizuki/items/814e0979217b1a25aa3e)
↑この記事の「８.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](https://qiita-image-store.s3.amazonaws.com/0/86468/17164858-12b3-b029-7dd2-a8a4c3958986.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に下記を追加

```Gemfile
group :production, :staging do
    gem 'unicorn'
end
```
そして`bundle install`を実行




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

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

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

```ruby: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コマンドの操作については[こちら](http://uguisu.skr.jp/Windows/vi.html)）

#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](https://qiita-image-store.s3.amazonaws.com/0/86468/df55a1ba-e141-a7b5-2bf4-526e28509608.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](https://qiita-image-store.s3.amazonaws.com/0/86468/b73893cc-45ba-6aa2-f0c4-fc3da6d852a2.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
```

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

```ruby: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](https://qiita-image-store.s3.amazonaws.com/0/86468/cabc87b3-1309-a4a6-1663-d1e0e5d1f0e4.png)


#参考

[ec2(amazon linux)にnginxを導入（デフォルトページの表示まで）](https://qiita.com/TetsuTaka/items/48433145c7f0ffa9e337)
[(デプロイ編②)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで](https://qiita.com/naoki_mochizuki/items/5a1757d222806cbe0cd1)
[Rails4 & Unicorn & Nginx & EC2でサーバー構築](https://qiita.com/kappy0322/items/fcb195391d46dd3213e7)
[AWSのEC2上でRails+Unicorn+Nginxを実現する](https://gist.github.com/honjo2/5023446)
[Amazon LinuxにRuby on Rails環境構築(rbenv + ruby-build + Ruby 2.2.1 + Rails 4.2.1インストール)](https://qiita.com/na0AaooQ/items/5bd62e630a2faf051a52)