AWSへのRailsアプリのデプロイ その2

## はじめに
今回は以下の記事の続きです。アプリのデプロイまで行っていきます。
<a href="https://qiita.com/ysda/items/359ba0afa23741db192b">AWSへのRailsアプリのデプロイ その1
</a>

## データベースのインストール
以下のコマンドでバージョン5.6をインストールします。
バージョンについては、各々の環境ごとに適当なものを選択してください。

```
sudo yum -y install mysql56-server mysql56-devel mysql56
```
さっそくmysqlを立ち上げます。

```
sudo service mysqld start
```
mysqlのrootユーザーのパスワードを設定します。

```
sudo /usr/libexec/mysql56/mysqladmin -u root password 'ここにパスワードを入力'
```
パスワードが設定できたか確認します。

```
mysql -u root -p
```
パスワードの入力を促されるため、先ほど設定したパスワードを入力します。

```
Enter password: 
```
mysqlへのログインが正常終了すれば「mysql>」が表示されSQL文を実行できるようになります。


```
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.47 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
```
これでmysqlのインストールは完了です。quitでログアウトしておきましょう。

```
mysql> quit
```

## EC2インスタンスからGitHubにSSH接続する
デプロイを行う際にGitHubからEC2へコードをクローンする必要があります。
以下のコマンドで公開鍵と秘密鍵のペアを作成しましょう。

```
ssh-keygen -t rsa -b 4096
```
これで.sshディレクトリの配下に鍵ができるので、catで公開鍵の内容を確認しGitHubに登録します。

```
cat /home/ec2-user/.ssh/id_rsa.pub
```

以下のURLからGitHubに公開鍵を登録しましょう。
https://github.com/settings/keys

![スクリーンショット 2020-05-31 19.32.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/6832e126-c13b-a926-f89c-98db1c8bdca8.png)
これでGithubにアクセスできるはずなので、EC2上からsshコマンドを実行してみましょう。
「Hi!"ユーザー名"」 と表示されればOKです。

```
ssh git@github.com
```

## アプリケーションサーバ(unicorn)の設定。
unicornの設定を行うため、まずはローカルでの作業を行います。Gemfileに以下を追記しましょう。
production do の中に記載することで、本番環境でのみunicornを使うことになります。

```
group :production do
  gem 'unicorn', 'インストールしたいバージョン'
end
```
gemのインストールも忘れずに。

```
bundle install
```
ちょっと長いですが、config/unicorn.rbを以下のように編集します。

```
app_path = File.expand_path('../../', __FILE__)

worker_processes 1

working_directory app_path

pid "#{app_path}/tmp/pids/unicorn.pid"

listen 3000

stderr_path "#{app_path}/log/unicorn.stderr.log"

stdout_path "#{app_path}/log/unicorn.stdout.log"

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
```

あとはmasterブランチにpushして完了です。

## GitHubからコードをクローンする
EC2インスタンスにディレクトリを作り、権限をec2-userに変更します。

```
sudo mkdir /var/www/
sudo chown ec2-user /var/www/
```

コードをクローンするためにはリポジトリのURLが必要なので、以下の赤枠内のボタンからURLを取得します。
![スクリーンショット 2020-05-31 23.40.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/73fd3207-b4b3-a55f-3dfd-9ae25e692002.png)
取得したURLでコードをクローンしましょう。

```
cd /var/www/
git clone https://github.com/naoto-ysd/freemarket.git
```
この時点で/var/wwwの配下にアプリがクローンされていると思います。
アプリのディレクトリ内に移動し、各種設定を行いましょう。

```
$ pwd
/var/www
$ ls -l
合計 4
drwxrwxr-x 15 ec2-user ec2-user 4096  5月 31 14:43 アプリ名
```

## Swap領域を用意する
Swap領域を用意し、メモリ不足に備えておきましょう。
ホームディレクトリで以下のコマンドを入力。

```
sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512
```
```
sudo chmod 600 /swapfile1
```
```
sudo mkswap /swapfile1
```
```
sudo swapon /swapfile1
```

## gemのインストール
一旦アプリをクローンしたディレクトリに移動します。

```
cd  /var/www/アプリ名
```
本番環境でgemを管理するためにbundlerをインストールします。
ローカルで以下のコマンドを実行してbundlerのバージョンを確認しましょう。

```
bundler -v
```
これで、ローカル側で使っているバージョンが分かりましたので、EC2上でbundlerのバージョンを指定してインストールします。

```
gem install bundler -v バージョン
```
bundle installも忘れず実行。

```
bundle install
```

## 環境変数の設定
パスワードなどのセキュリティに関わる情報は環境変数に設定します。
まずsecret_key_baseを作成しましょう。
EC2上で以下を実行します。

```
cd /var/www/アプリのディレクトリ
```
rake secretでcookieの暗号化に文字列を作成します。
このコマンドで生成する文字列は、後から環境変数に設定するのでコピーしておきましょう。

```
rake secret
```
/etc/environmentを編集して環境変数を設定しましょう。

```
sudo vim /etc/environment
```
```
DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'
SECRET_KEY_BASE='先程コピーしたsecret_key_base'
```
環境変数を反映させるため、一度ここでログアウトしてから再度EC2にログインてください。
再度ログインしたら、環境変数が設定されているはずなので、envコマンドで確認します。

```
env | grep DATABASE_PASSWORD
env | grep SECRET_KEY_BASE
```
## ポートの解放
現時点ではEC2インスタンスがhttpで通信できない状態です。
インバウンドルールを編集し、ポートを解放してあげましょう。
![スクリーンショット 2020-06-01 2.10.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/9d16fc77-4abe-e522-cc61-74794349d5b2.png)

先程作成したrunicorn.rbでlisten 3000と記述したので、今回デプロイするアプリではポート番号3000を使うことになります。
インバウンドルールにポート番号3000を追加して、作業は完了です。
![スクリーンショット 2020-06-01 2.30.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/737db73a-76ca-fc1b-8eea-a2b4a8780cf8.png)

## Railsを起動させる。
Railsを起動させる前にDBの設定を行います。
ローカル環境でdatabase.ymlを編集してproduction: 以下を変更しましょう

```
production:
  <<: *default
  database: "アプリ名によって異なる。変更不要"
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock
```
ローカルでの変更をコミットしてGithubにプッシュした後、EC2インスタンス上にコードを反映させます。

```
git pull origin master
```
EC2インスタンス上にデータベースを作成してマイグレーションしましょう。

```
rails db:create RAILS_ENV=production
rails db:migrate RAILS_ENV=production
```
このままの状態だとアセットファイル(画像やjsのこと)がコンパイルされていないので、ビューが崩れてしまいます。
事前にコンパイルを行っておきましょう。

```
rails assets:precompile RAILS_ENV=production
```

それではEC2インスタンスでRailsを起動させます。
アプリのディレクトリに移動してから、ユニコーンを起動させるコマンドでRailsを起動させることができます。
-cオプションで設定ファイルのパスを指定し、-E で本番環境で作動させています。

```
cd /var/www/アプリ名/
```
```
bundle exec unicorn_rails -c config/unicorn.rb -E production -D
```
ここまで出来ればデプロイできたはずなので、実際にブラウザでアプリにアクセスしてみましょう。
http://"Elastic IP":3000
エラーが起きた場合、以下のファイルにエラーログが出力されているので、こちらを確認してみてください。

```
tail -f /var/www/freemarket/log/unicorn.stderr.log
```

## ウェブサーバのインストール
ウェブサーバとしてNginxをEC2にインストールします。

```
sudo yum -y install nginx
```
インストールが終了したら、/etc/nginx/conf.d/rails.confを以下のように編集しましょう。
アプリケーション名やElasticIPは適宜読み替えてください。

```
upstream app_server {
  server unix:/var/www/アプリケーション名/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name Elastic IP;

  client_max_body_size 2g;

  root /var/www/アプリケーション名/public;

  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の権限も変更しておきます。

```
sudo chmod -R 775 /var/lib/nginx
```
nginxを再起動させて設定ファイルを読み込ませましょう。

```
sudo service nginx restart
```
##unicorn関係の修正
現在はunicorn.rbのlistenという項目に3000が指定されていると思います。
それを以下のように修正し、Githubへプッシュしましょう。

```
listen "#{app_path}/tmp/sockets/unicorn.sock"
```
EC2への反映も忘れずに。

```
git pull origin master
```
unicornを再起動させるため、unicornのプロセスIDを確認します。

```
ps aux | grep unicorn

ec2-user 14750  0.0 11.6 504768 117792 ?       Sl   Jun01   0:02 unicorn_rails master -c config/unicorn.rb -E production -D                                                                                            
```
プロセスID14750をkillしましょう。

```
kiill 14750
```
これでRailsを再起動させればアプリケーションにアクセスできるはずです。
http://"Elastic IP"　(URLにポート番号の指定は不要です。)

```
RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
```
## Railsの起動でエラーが出たら
以下の方法でエラーの解決方法を調査してみましょう。

・ログの確認
/var/www/アプリ名/log/unicorn.stderr.log
/var/log/nginx/error.log

・以下を再起動してみる
MySQL
Nginx
EC2

## いったん完結
アプリのデプロイまで出来たため、前回の記事と合わせていったん完結です。
私の気力次第で自動デプロイについての記事も書きます。