EC2でRails6を起動してみた

# はじめに
オリアプをherokuにデプロイしていますが、AWSやインフラも勉強したいと思いEC2でもデプロイしてみることにしました。
今回は、EC2でRails6を起動しましたので備忘録として残したいと思います。

# EC2上でRails6を起動するための達成

まずは、アプリケーションのコードをGitHubからEC2サーバへクローンします。
これは、デプロイできるIPアドレスを持ったEC2サーバー上でアプリケーションを動かすためです。
しかし、このままEC2サーバにクローンしてもエラーが出てしまいます。
GitHubはEC2のことを認証していないためです。

EC2サーバーのsshキーペアを作ります。

```
[ec2-user@ip-ご自身のIP ~]$ ssh-keygen -t rsa -b 4096
```

そして、生成されたキーをcatコマンドで確認します。

```
[ec2-user@ip-ご自身のIP ~]$ cat ~/.ssh/id_rsa.pub
表示された英数字を全てコピーします。
```

GitHubのページへ飛び、「New SSH key」をクリックし、
①Title　任意のタイトルを入力
②key コピーしたキーを貼り付け
「Add SSH key」をクリック保存します。

念のためssh接続できるか確認します。

```
[ec2-user@ip-ご自身のIP ~]$ ssh -T git@github.com
successfullyと出たらオッケーです。
```

# アプリケーションサーバーを設定
「Unicorn」というツールを使用します。
ローカル環境では「rails s」コマンドでサーバー立ち上げますが、「Unicorn」を使用した場合は「unicorn_rails」コマンドで起動することができます。

```
Gemfile
group :production do
  gem 'unicorn', '5.4.1'
end
```

bundle installします。

config/unicorn.rbを作成します。

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

#エラーのログを記録するファイルを指定します
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
```

EC2にローカルの全内容を反映します。

```
#mkdirコマンドで新たにディレクトリを作成
[ec2-user@ip-ご自身のIP ~]$ sudo mkdir /var/www/

#作成したwwwディレクトリの権限をec2-userに変更
[ec2-user@ip-ご自身のIP ~]$ sudo chown ec2-user /var/www/

[ec2-user@ip-ご自身のIP ~]$ cd /var/www/

[ec2-user@ip-ご自身のIP www]$ git clone GitHubのアプリのコードURLをはる
```

# EC2を拡張します。

EC2のメモリを増量するために「Swapファイル」を使用します。

```
[ec2-user@ip-ご自身のIP ~]$ sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512

[ec2-user@ip-ご自身のIP~]$ sudo chmod 600 /swapfile1

[ec2-user@ip-ご自身のIP ~]$ sudo mkswap /swapfile1

[ec2-user@ip-ご自身のIP ~]$ sudo swapon /swapfile1

[ec2-user@ip-ご自身のIP ~]$ sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab'
```

以上で確保完了です。

#EC2ないでGemをインストールします。

```
[ec2-user@ip-ご自身のIP www]$ cd  /var/www/開発中のアプリケーション

# rubyのバージョンを確認
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ ruby -v

# 「2.1.4」の箇所は、ローカルで確認したbundlerのバージョンを導入します
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ gem install bundler -v 2.1.4

# 以下のコマンドは、処理に数分以上かかる場合があります
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ bundle install
```

# 環境変数を設定します。

Railsアプリケーションを動作させる際に必ず用意する必要がある「secret_key_base」を環境変数にします。

```
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ rake secret
ここに出てくる文字列は全てコピーしておきます。
```

環境変数は、「/etc/environment」というファイルに保存します。
その時に、「sudo」というオプションを使います。
sudoとは、「全権限を持った上でコマンドを実行する」というオプションです。
「/etc以下のファイル」は強い権限がないと書き込み、保存ができないため、コマンドの頭に「sudo」をつけます。

```
[ec2-user@ip-ご自身のIP ~]$ sudo vim /etc/environment

DATABASE_PASSWORD='データベースのrootユーザーのパスワード'
SECRET_KEY_BASE='さきほど作成したsecret_key_base'

#他にローカルで設定した環境変数がある場合は、記述します。

escキー→:wqで保存して終了します。
```

一度、環境変数が設定されているか、確認するためログアウトしてもう一度EC2にログインします。

ログイン後、「envコマンド」、「grepコマンド」を使って全環境変数を表示し確認します。

```
[ec2-user@ip-ご自身のIP ~]$ env | grep SECRET_KEY_BASE
# この上記のように反映されているか全て確認しておきます。
```

# ポートを確認します。
EC2のホームページに戻り、ポートを3000に変更します。
先ほど、config/unicorn.rbで「listen 3000」と記述したのは「Railsのサーバーを3000番ポートで起動する」という意味です。

それでは、EC2内のセキュリティグループのボードを設定します。
EC2インスタンス画面にいき、「セキュリティ」をクリックし、セキュリティグループをクリックします。
インバウンドルールを編集をクリックし、

「ルールを追加」で

|タイプ      |プロトコル|ポート番号|送信元           |
|----------|-------|--------|----------------|
|カスタムTCP |TCP    |３０００    |カスタム/0.0.0.0/0|
変更後は「ルールを保存」をクリックします。

# Railsを起動します。

本番環境でRailsを起動するには、「unicorn_rails」コマンドを使います。

```
config/database.yml
production:
  <<: *default
  database:こちらは編集しないでください
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

編集します。
```

ここで、リモートリポジトリも更新しておきます。
その後、サーバー上のアプリケーションにも反映させておきます。

```
[ec2-user@ip-ご自身のIP <リポジトリ名>] git pull origin master
```

次に、DBを本番環境で作ります。

```
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ rails db:create RAILS_ENV=production
Created database '<データベース名>'
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ rails db:migrate RAILS_ENV=production

```
RAILS_ENV=productionとは、「railsの環境が本番環境ですよ」ということを意味します。

DBを起動させます。

```
[ec2-user@ip-ご自身のIP ~]$ cd /var/www/[リポジトリ]
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D
```

アセットファイルをコンパイルします。
簡単にいうと本番環境でもレイアウトが崩れないようにしますということです。

```
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ rails assets:precompile RAILS_ENV=production
```


本番環境のRailsを再起動します。
「ps」コマンドを使います。これは現在動いているプロセスを確認する為のコマンドになります。

```
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ ps aux | grep unicorn
#下記に以下の表示がされるはずです。

ec2-user 17877  0.4 18.1 588472 182840 ?       Sl   01:55   0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881  0.0 17.3 589088 175164 ?       Sl   01:55   0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911  0.0  0.2 110532  2180 pts/0    S+   02:05   0:00 grep --color=auto unicorn

```
ec2-user 17877  0.4 18.1 588472 182840 ?       Sl   01:55   0:02 unicorn_rails master -c config/unicorn.rb -E production -Dの「 unicorn_rails master」がプロセスの本体であり、「17877」がプロセスIDです。
なので、現在本番環境が起動しているということになります。

それでは、次に現在起動しているプロセスを停止させるコマンドです。
「kill」コマンドです。

```
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ kill <確認したunicorn rails masterのプロセスid>
```
これで、Unicornの停止が完了です。

再度、Railsを再起動するコマンドを実行します。

```
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
```

RAILS_SERVE_STATIC_FILES=1とは、「Railsがコンパイルされたアセットを見つけるよう指定する役割」があります。
以上で立ち上げられているはずなので、
ブラウザでご自身の「Elastic IP」を入力してみてください。

# 最後に
この上記の作業により無事にEC2ないでRailsを起動することができました。
中々、工程が多いので難しく感じてしまいましたが、一つ一つの動作を分解してみれば、今までローカルでもやっていた手順とあまり変わりないのかななんて感じます。
少しずつ慣らして、クラウドもいじれるように頑張ります！

ここまで読んでいただきありがとうございました！