Rails アプリを EC2 にデプロイしよう！（デプロイ編）

Rails アプリを Amazon Web Service を使ってデプロイするまでの手順をまとめました。
次の順番でデプロイまで持っていきます。

1, 準備編
2, サーバー構築編
3, 環境構築編
4, デプロイ編

今回は「デプロイ編」です。
1 ~ 3 を読んでない方は先に読んでください。
[Rails アプリを EC2 にデプロイしよう！（準備編）](https://qiita.com/tao066/items/9eb25b840694f8805221)
[Rails アプリを EC2 にデプロイしよう！（サーバー構築編）](https://qiita.com/tao066/items/11575932e6aa05c3afdd)
[Rails アプリを EC2 にデプロイしよう！（環境構築編）](https://qiita.com/tao066/items/6d1c535b4aec4e2ed448)

# Gem のインストール

前回までに、アプリのクローンを完了しました。
今回の最初の作業は、gem のインストールです。

まずは bundler を設定しましょう。
bundler は本アプリ使用している bundler とバージョンが一致しているものを選択しましょう。

```
[minato@ip-192-168-10-49 ~]$ /var/www/rails/sample_app
[minato@ip-192-168-10-49 sample_app]$ gem install bundler 2.1.4
Fetching bundler-2.1.4.gem
Successfully installed bundler-2.1.4
Parsing documentation for bundler-2.1.4
Installing ri documentation for bundler-2.1.4
Done installing documentation for bundler after 3 seconds
1 gem installed
```

次に、Gemfile の中身を確認しましょう。
今回は次の gem を想定しています。

```rb:Gemfile
gem 'rails', '~> 5.2.2'
gem 'bootsnap', require: false
gem 'puma', '~> 3.7'
gem 'mysql2', '>= 0.4.10', '< 0.5'
```

確認したら `bundle install` を行いましょう。

```
[minato@ip-192-168-10-49 sample_app]$ bundle _2.1.4_ install --path vendor/bundle --without development:test
```

無事にインストールできれば OK です。

# アプリの secret_key_base の設定

次に secret_key_base の設定を行います。
今回は `Rails 5.2` なので、`config/credentials.yml.enc` を読み込むために
`config/master.key` をEC2でも作成しましょう。
**これがないと本番環境で起動することができません。**

1. **ローカル環境** にある `config/master.key` の中身をコピーします。
2. **サーバー環境** で `config/master.key` を新規作成して先ほどコピーした内容をペーストします。

次のコマンドで secret_key_base が確認できれば OK です。

```terminal
[minato@ip-192-168-10-49 sample_app]$ EDITOR="vim" bundle exec rails credentials:edit
```

# Puma の設定

次は Puma の設定を行います。
Puma はアプリケーションサーバーの一種です。

早速設定していきます。

```rb:config/puma.rb
case ENV['RAILS_ENV']
when "production"
  environment "production"
  port 3000
  threads 16, 16
  daemonize true

  # sample_app の部分は自身のアプリケーションの名前に変更してください。
  app_dir = File.expand_path("/var/www/rails/sample_app", __FILE__)

  bind  "unix://#{app_dir}/tmp/sockets/puma.sock"
  pidfile      "#{app_dir}/tmp/pids/puma.pid"
  state_path   "#{app_dir}/tmp/pids/puma.state"

  stdout_redirect nil, "#{app_dir}/log/puma.stderr.log", true

  plugin :tmp_restart
else
  environment "development"
  port 3000
  threads 5, 5

  pidfile    "tmp/pids/puma.pid"
  state_path "tmp/pids/puma.state"

  stdout_redirect nil, "log/puma.stderr.log", true

  plugin :tmp_restart
end
```

ここら辺は設定ファイルなので、詳細には追いません。
また、設定ファイルの記述が終わったら、次のコマンドも実行してください。

```
[minato@ip-192-168-10-49 sample_app]$ mkdir tmp/sockets
```

`puma.sock` を作成先のディレクトリを作成しています。
これで Puma の設定が完了です。

# Nginx の設定

お次は Nginx です。「エンジンエックス」と読むそうです。
この Nginx は Web サーバーにあたります。

早速下記コマンドを打ち込んでください。

```terminal
[minato@ip-192-168-10-49 ~]$ cd ~
[minato@ip-192-168-10-49 ~]$ sudo yum install nginx
[minato@ip-192-168-10-49 ~]$ sudo vim /etc/nginx/conf.d/sample_app.conf
```

vim コマンドで作成した nginx の設定ファイルを次のように記述します。

```config:/etc/nginx/conf.d/sample_app.conf
# アクセスログ・エラーログの出力先を設定する
# sample_app の部分は自身のアプリケーションの名前に変更してください
error_log  /var/www/rails/sample_app/log/nginx.error.log;
access_log /var/www/rails/sample_app/log/nginx.access.log;

upstream puma {
    # puma.sock の場所を指定する
    # sample_app の部分は自身のアプリケーションの名前に変更してください
    server unix:///var/www/rails/sample_app/tmp/sockets/puma.sock;
}

server {
    listen 80;

    # server_name を設定します。自身のパブリックDNSに変更してください。
    server_name ec2-52-198-194-39.ap-northeast-1.compute.amazonaws.com;

    client_max_body_size 500M;
    keepalive_timeout 5;

    # パブリックページの場所をここで設定します。
    # sample_app の部分は自身のアプリケーションの名前に変更してください
    root /var/www/rails/sample_app/public;

    location / {
        try_files $uri $uri/index.html $uri.html @app;
    }
    
    location @app {
        proxy_read_timeout    300;
        proxy_connect_timeout 300;
        proxy_redirect        off;
        client_max_body_size  1G;

        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;

        proxy_pass http://puma;
    }

    # Rails のエラーページを表示する
    # sample_app の部分は自身のアプリケーションの名前に変更してください
    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /var/www/rails/sample_app/public;
    }
}
```

ここも設定ファイルなので詳細には追いません。
また、AWSが生成するドメイン名が
`ec2-52-198-194-39.ap-northeast-1.compute.amazonaws.com`
と大変長いので、次のコマンドを実行して設定を変えます。

```
$ sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.old
$ sudp vim /etc/nginx/nginx.conf
```

```config:nginx.conf
# ...

http {
    # ...
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
    server_names_hash_bucket_size 128; # これを追記
    # ...
}
```

最後に、次のコマンドを実行してください。

```terminal
[minato@ip-192-168-10-49 conf.d]$ cd /var/lib
[minato@ip-192-168-10-49 lib]$ sudo chmod -R 775 nginx
```

post メソッドでもエラーが出ないようにするためのものです。
これにて Nginx の設定完了です。

# MySQLの設定
次は DB です。
アプリケーションの DB が MySQL で作成されている前提で話を進めていきます。

まずは database の設定を行います。

```
[minato@ip-192-168-10-49 sample_app]$ vim config/database.yml
```

設定内容は次のとおりです。

```config/database.yml
production:
  <<: *default
  adapter: mysql2
  port: 3306
  database: sample_app_production
  username: root
  password:
  encoding: utf8
  charset: utf8
  collation: utf8_general_ci
```

保存したら次のコマンドを実行していきましょう。

```terminal
# mysql を起動
[minato@ip-192-168-10-49 sample_app]$ sudo service mysqld start

# mysql.sock を /tmp に移動する
[minato@ip-192-168-10-49 sample_app]$ ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock

# 本番環境用の db を作成する
[minato@ip-192-168-10-49 sample_app]$ RAILS_ENV=production bundle exec rake db:create

# 本番環境用の db の migrate を実行する
[minato@ip-192-168-10-49 sample_app]$ RAILS_ENV=production bundle exec rake db:migrate
```

`seed` を予め設定する場合はこのタイミングで実行してください。

# Rails アプリの起動

このコマンドで puma を起動しましょう。
これで Rails アプリが起動します。

```
[minato@ip-192-168-10-49 sample_app]$ RAILS_ENV=production bundle exec puma
```

インターネットからアクセス出来る様に
次のコマンドで nginx を起動します。

```
[minato@ip-192-168-10-49 sample_app]$ sudo service nginx start
```

自身のパブリックDNSを使用してブラウザからアクセスしてみましょう
`http://ec2-52-198-194-39.ap-northeast-1.compute.amazonaws.com/`

無事にアクセスできれば OK です。

# 停止方法

最後に停止方法について記述しておきます。

```
$ sudo service nginx stop
```

```
$ bundle exec pumactl halt
```

# 最後に

これでデプロイを完了することができました。

でも、まだアクセス出来てない方もいるかと思います。
そんな方はググったり、質問したりして問題解決を頑張ってください。
当たりが強いエンジニアもいますが、優しく教えてくれるエンジニアもいます。

自分は大学一回生でこのデプロイ作業を初めて行いましたが、完了するのに１週間もかかりました。
それでも大学の先輩に質問したり、頑張って英語の公式ドキュメントを読んだり、
ひたすらググったりすることでなんとかデプロイを完了しました。

このデプロイ経験で多くの知識や経験を得ました。
特に、根気よく問題解決する精神は鍛えられました。

根気よく、適度に休憩をとりながら、デプロイ作業を頑張ってください。