AWSを使ってアプリケーションを公開する手順(6)Nginxを導入する

#はじめに
AWSを使ってアプリケーションを公開する手順を記載していく。
この記事ではWebサーバであるNginxを導入する。

#Nginxをインストールする
##Nginxとは
NginxとはWebサーバの一種である。
ユーザのリクエストに対して静的なコンテンツの取り出し処理を行い、動的なコンテンツの生成をアプリケーションサーバに依頼する。

##「.ssh」ディレクトリに移動する
以下のコマンドを実行し、「.ssh」ディレクトリに移動する。

```
cd ~/.ssh/
```

##ssh接続
以下のコマンドを実行し、EC2インスタンスにsshでアクセスする。
(ダウンロードしたpemファイル名が「xxx.pem」、ElasticIPが12.345.67.890の場合)

```
ssh -i xxx.pem ec2-user@12.345.67.890
```

##Nginxのインストール
以下のコマンドを実行し、Nginxをインストールする。

```
sudo yum -y install nginx
```

#Nginxの設定ファイルを編集する
以下のコマンドを実行しvimを使ってNginxの設定ファイルを編集する。
/etcディレクトリ以下のファイルは権限がないと読み書き保存ができないため、sudoで実行する。

```
sudo vim /etc/nginx/conf.d/rails.conf
```

以下のようにrails.confを編集する。
今回はアプリケーション名が「testapp」、Elastic IPが「12.345.67.890」の場合を例として進める。

```ruby:rails.conf
upstream app_server {
  # Unicornと連携させるための設定。
  server unix:/var/www/testapp/tmp/sockets/unicorn.sock;
}

# {}で囲った部分をブロックと呼ぶ。サーバの設定ができる
server {
  # このプログラムが接続を受け付けるポート番号
  listen 80;
  # 接続を受け付けるリクエストURL ここに書いていないURLではアクセスできない
  server_name 12.345.67.890;

  # クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
  client_max_body_size 2g;

# 接続が来た際のrootディレクトリ
  root /var/www/testapp/public;

# assetsファイル(CSSやJavaScriptのファイルなど)にアクセスが来た際に適用される設定
  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

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

  location @unicorn {
    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;
  }

  error_page 500 502 503 504 /500.html;
}
```

##Nginxの権限を変更する
以下のコマンドを実行してNginxの権限を変更する。
ここで権限を変更することでPOSTメソッドでエラーが出なくなる。

```
cd /var/lib
```

```
sudo chmod -R 775 nginx
```

###「-R」オプション
「-R」オプションは再帰的に変更するためのオプションである。
つまり、そのディレクトリとディレクトリ内の全てのファイルの権限を変更する。

###POSTメソッドとは
HTTP通信でクライアントからWebサーバに送るリクエストの一つで、URLで指定したプログラムなどに対してクライアントからデータを送信するためのもの。大きなデータやファイルをサーバに送るために使われる。

##Nginxを再起動する
以下のコマンドを実行し、Nginxを再起動し、設定ファイルを再読み込みする。

```
cd ~
```

```
sudo service nginx restart
```

#unicornの設定を修正する
Nginxを介した処理を行うため、unicornの設定を再度修正する。

##unicorn.rbを編集する
開発環境でconfig/unicorn.rbを以下のように編集する。
編集したら、コミットとプッシュ忘れずに行う。

```ruby:config/unicorn.rb
#サーバ上でのアプリケーションコードが設置されているディレクトリを変数に入れておく
app_path = File.expand_path('../../', __FILE__)

#アプリケーションサーバの性能を決定する
worker_processes 1

#アプリケーションの設置されているディレクトリを指定
working_directory app_path

#Unicornの起動に必要なファイルの設置場所を指定
pid "#{app_path}/tmp/pids/unicorn.pid"

#ポート番号を指定
listen "#{app_path}/tmp/sockets/unicorn.sock"

#エラーのログを記録するファイルを指定
stderr_path "#{app_path}/log/unicorn.stderr.log"

#通常のログを記録するファイルを指定
stdout_path "#{app_path}/log/unicorn.stdout.log"

#Railsアプリケーションの応答を待つ上限時間を設定
timeout 60

preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true

check_client_connection false

run_once = true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) &&
    ActiveRecord::Base.connection.disconnect!

  if run_once
    run_once = false # prevent from firing again
  end

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exist?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH => e
      logger.error e
    end
  end
end

after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end
```

##本番環境に反映する
以下のコマンドを実行し編集内容を本番環境に反映する。

```
cd /var/www/testapp(アプリケーションのリポジトリ名が「testapp」の場合)
```

```
git pull origin master
```

##unicornを再起動する
以下のコマンドを実行し、unicorn masterのプロセスIDを確認する。

```
ps aux | grep unicorn
```

以下のコマンドを実行し、確認したプロセスIDをkillする。
(ここではunicorn masterのプロセスIDが17877であったとする)

```
kill 17877
```

以下のコマンドを実行し、unicornを起動する。

```
RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
```

#ブラウザからElastic IPでアプリケーションにアクセスする
ブラウザからElastic IPでアプリケーションにアクセスする。(今回は:3000をつけなくてよい)
このとき、unicornが起動している必要がある。

##エラーが出る場合に確認すること
- 502 bad gatewayとエラーが出る場合は/var/log/nginx/error.logを確認する
- /var/www/testapp/log/unicorn.stderr.logを確認しエラーがないか確かめる(リポジトリ名がtestappの場合)
- railsを起動しているか
- EC2インスタンスの再起動を行う(本番環境でMySQLとNginxの再起動が必要)

#補足
##Webサーバとは
外部から送られてきたリクエストを受け取り、処理を加える。
NginxはWebサーバの一種。
以下の役割がある。

- 静的なコンテンツをレスポンスとしてクライアントに返す
- 動的なコンテンツの生成をアプリケーションサーバに依頼する
- アプリケーションサーバから返ってくる処理結果をレスポンスとしてクライアントに返す

静的なコンテンツとは、リクエスト毎に内容が変わらないファイル。
表示するものが決まっているcssや画像ファイルなど。
動的なコンテンツとは、リクエスト毎に内容が変化するファイル。
データベースから検索条件に該当するデータを取得して表示するファイルなど。

##アプリケーションサーバとは
動的なコンテンツを生成し、処理結果をWebサーバに返す。
Unicornはアプリケーションサーバの一種。
以下の役割がある。

- Webサーバから依頼された情報を基に動的なコンテンツの生成を行う
- 処理結果をWebサーバに返す

# 関連記事
[AWSを使ってアプリケーションを公開する手順(1)AWSアカウントの作成](https://qiita.com/osawa4017/items/78ee5912084dd83c5a0d)
[AWSを使ってアプリケーションを公開する手順(2)EC2インスタンスの作成](https://qiita.com/drafts/ec5aa2965a89320b074d)
[AWSを使ってアプリケーションを公開する方法(3)EC2インスタンスの環境構築]
(https://qiita.com/osawa4017/items/8dc09203f84e04bf0e66)
[AWSを使ってアプリケーションを公開する手順(4)データベースの作成]
(https://qiita.com/osawa4017/items/7dba25f4fa30ab0b1246)
[AWSを使ってアプリケーションを公開する手順(5)アプリケーションを公開する]
(https://qiita.com/osawa4017/items/6f3125fcc21f73024311)