Ruby on Railsで作ったアプリをAWS EC2で公開する

#はじめに
まずこちらの記事で、AWSのCloud9にてRuby on Railsを使ったWEBアプリのデモ開発を行った。
[Ruby on Railsでのアプリ開発（初心者）](https://qiita.com/Moriyoshi_05/items/63aa3272a13544be0744)
※内容は備忘録代わりなので、煩雑です。
これらのアプリは全てgithubにpushしてあります。

今回はアプリをAWSのEC2で公開する手順について備忘録として残す。
参考にしたのは下記サイトとなる。
こちらはAmazon Linux AMIで実施しているので、今回の手順と一部異なります。
・[Ruby on Rails】AWS を利用したデプロイ（AWS & Nginx & Unicorn & Rails）How to deploy a Rails App to EC2（2020年版）](https://www.youtube.com/watch?v=DYoXhTUfm98)
・[AWS & Nginx & Unicorn & Ruby on Rails](https://hackmd.io/4_1NYUTBSaSsOC8cur7WhA?view)

今回、VPCの設定やEC2の起動は省略する。
＜EC2の環境＞

+ AMI：Amazon Linux 2 AMI
+ インスタンスタイプ：2.micro
+ パブリックIP：EIPで固定

ruby on railsに関わるバージョンは以下とする。
開発環境ではrvmで実施したが、EC2に対して導入がうまくいかなかったので、rbenvとした。

＜各バージョン＞

+ rubyのバージョン切替ソフトウェア：rbenv
+ ruby：2.5.1　※バージョンはシビア
+ gem：3.0.8
+ rails：5.2.1　※バージョンはシビア
+ プロジェクトは**qanda**とした

#EC2へのSSHログイン
ダウンロードしたキーペアの権限変更をした後に、ログインが必要。
ここでキーペアはRails-web.pemとする。

```bash
mv Downloads/Rails-web.pem .ssh/
ssh -i .ssh/ec_site.pem ec2-user@xxx.xxx.xxx.xxx
```

ちなみに「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」といったエラーが出た場合はSSHコマンドにオプションをつけて実行する。

```bash
ssh -i .ssh/ec_site.pem ec2-user@xxx.xxx.xxx.xxx -o 'StrictHostKeyChecking no'
```

#EC2インスタンスの環境構築
##必要パッケージをインストール

```bash
sudo yum update
```

```bash
sudo yum -y install git make gcc-c++ patch openssl-devel libyaml-devel libffi-devel libicu-devel libxml2 libxslt libxml2-devel libxslt-devel zlib-devel readline-devel mysql mysql-server mysql-devel ImageMagick ImageMagick-devel epel-release sqlite sqlite-devel
```

##rbenvのインストール
```bash
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
$ sudo ~/.rbenv/plugins/ruby-build/install.sh
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
```

##rubyのインストール（バージョンは2.5.1）
installには時間がかかります。

```bash
$ rbenv install 2.5.1
$ rbenv global 2.5.1
$ rbenv rehash
```

##node.jsのインストール
```bash
$ curl --silent --location https://rpm.nodesource.com/setup_12.x | sudo bash -
$ sudo yum install -y nodejs
```

##railsのインストール（バージョンは5.2.1）
```bash
gem install rails -v 5.2.1
```

##bundlerをインストール
cloud9のbundlerバージョンを確認したが、cloud9に導入されていなかったため、
とりあえずインストールをしておいた。
※必要はなかったかもしれない。

```bash:cloud9上でのコマンド
$ gem install bundler
$ bundler -v
```

cloud9にBundler version 1.17.3がインストールされたのでバージョンを併せてEC2にインストールする。

```bash:EC2上でのコマンド
gem install bundler -v 1.17.3
```

##gitとの連携、アプリのクローン
###鍵を作る
パスワードを求められるが、空白で全てEnter

```bash
$ cd ~/.ssh
$ ssh-keygen -t rsa
$ cat id_rsa.pub
```

最後のcatで表示されたキーを自分のgithubのsshKEY登録した後に、
こちらのコマンドでgitとの連携を確認する。

```bash
sh -T git@github.com
```

###クローン
アプリのためのディレクトリを作成する。

```bash
$ cd /
$ sudo chown ec2-user var
$ cd var
$ sudo mkdir www
$ sudo chown ec2-user www
$ cd www
$ sudo mkdir rails
```

クローンを進める。

```bash
$ cd rails
$ git clone git@github.com:＜自分のリポジトリ＞　（SSHクローンのアドレス）
$ cd qanda
$ bundle
```

もし、bundle実行時に次のようなエラーが出た場合、
msgpackをアップデートしてあげる。
>Your bundle is locked to msgpack (1.4.1)

```bash
bundle update msgpack
```

その後に、再度bundle実行する。

##マスターキーの登録
cloud9上でmaster.keyを確認してコピーする。
configフォルダに格納されている。

EC2上で、上記でコピーした値をmaster.keyに登録する。

```bash
vi config/master.key
```

credentials.ymlの設定をする。

```bash
EDITOR=vim bin/rails credentials:edit
```

以下の値を追加する。
パスワードはrootの条件を満たす必要がある。
**「大文字、小文字、特殊文字(アスタリスク等)を含む」**

```yml
db:
  database: qanda
  username: root
  password: xxxxxxxx
  socket: /var/lib/mysql/mysql.sock
```

##MySQLの設定
linux2だと既にインストール済みのmariadbが邪魔をして、うまくMySQLを起動できなかった。
そのため、こちらをまずは実行してから起動をかけるとうまくいった。

```bash:MySQLのリポジトリをインストール
sudo yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-2.noarch.rpm
```

```bash：MySQLをインストール
sudo yum install -y mysql-community-server
```

```bash:起動
sudo service mysqld start
```

```bash:ステータス
sudo service mysqld status
```

##MySQLのパスワード設定
パスワードも勝手に初期設定されていたため、
下記でパスワードを確認して、パスワード再設定を行った。

```bash:パスワードの確認
$ sudo su -
$ cat /var/log/mysqld.log | grep password
```

こちらが表示され、語尾が初期rootパスワードになる。
>[Server] A temporary password is generated for root@localhost: **xxxxxx**

その後、こちらのパスワードを使って、mysqlにログインする。
下記のコマンドを入力後に、先ほどのパスワードを入力する。

```bash:mysqlのログイン
mysql -u root -p
```

次に、設定したいパスワードを入力する。（credentials.ymlの値に合わせる）
ちなみにパスワード設定時に下記のエラーが出るとパスワード条件を満たしていない
>ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

```sql
mysql> ALTER USER 'root'@'localhost' identified BY 'xxxxx';
```

##database.ymlの編集
```bash
vi config/database.yml
```

下記のようにproductionを書き換える

```yml
production:
  <<: *default
  database: <%= Rails.application.credentials.db[:database] %>
  username: <%= Rails.application.credentials.db[:username] %>
  password: <%= Rails.application.credentials.db[:password] %>
  socket: <%= Rails.application.credentials.db[:socket] %>
```

##nginxの設定
AMI linux2の環境に合わせたインストール方法となっている。

```bash
$ sudo amazon-linux-extras install nginx1 -y
$ sudo vi /etc/nginx/conf.d/qanda.conf
```

こちらのコードを記入して保存する。

```conf
error_log  /var/www/rails/qanda/log/nginx.error.log;
access_log /var/www/rails/qanda/log/nginx.access.log;

upstream unicorn_server {
    server unix:/var/www/rails/qanda/tmp/sockets/.unicorn.sock fail_timeout=0;
}

server {
    listen 80;
    client_max_body_size 4G;
    server_name 52.23.9.110;

    keepalive_timeout 5;

    # Location of our static files
    root /var/www/rails/qanda/public;

    location ~ ^/assets/ {
        root /var/www/rails/qanda/public;
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://unicorn_server;
            break;
        }
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /var/www/rails/qanda/public;
    }
}
```

###権限の変更
```bash
$ cd /etc
$ sudo chown -R ec2-user nginx
$ ls -la | grep nginx
```

##Unicornの設定
Gemfileに以下を記述。
※開発環境（Cloud9）で入れておいてよいかもしれない

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

インストール実行する。

```bash
bundle install
```


設定を変更する。unicorn.conf.rbを開いて、コードを追記する。

```bash
vi config/unicorn.conf.rb
```

```rb
$worker  = 2
$timeout = 30
$app_dir = "/var/www/rails/qanda"
$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
```

マイグレーションの実行

```bash
bundle exec rake db:migrate RAILS_ENV=production
```

##yarnのインストール
コンパイルの時にyarnが必要とエラーが出たので、インストールしておく。

```bash
$ sudo yum -y install wget
$ sudo wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo
$ sudo curl --silent --location https://rpm.nodesource.com/setup_6.x | bash -
$ sudo yum install yarn -y
````

##assetsコンパイル実行
production.rbを編集して、下記の箇所を変更する。

```bash
vi config/environments/production.rb
```

```rb
config.assets.js_compressor = Uglifier.new(harmony: true)
```

コンパイルを実施する。

```bash
bundle exec rake assets:precompile RAILS_ENV=production
```

#確認
AWSのコンソール上で、EC2の再起動する。

Nginxを起動する。

```bash
sudo service nginx start
```

Unicornの起動

```bash
$ cd /var/www/rails/qanda/
$ bundle exec unicorn_rails -c /var/www/rails/qanda/config/unicorn.conf.rb -D -E production
```

Unicornの起動の確認

```bash
ps -ef | grep unicorn | grep -v grep
```

EC2に設定されているパプリックIPかEIPでサイトアクセスすると、アプリの起動が確認できる。

#最後に
AMIをLinux2を使うことで、参考にした手順と異なる箇所がいくつかあり、
調べた手順を含めると、うまく進めることができた。
調べながら実施したので、再度再現して上手くいくかは確かめたい。