yuuki blog

プログラミング をアプトプットしています。

AWS (手動デプロイ)Rails環境

EC2のサーバーに開発中のアプリケーションのコードをクローンする準備をしよう

まず、アプリケーションのコードをGitHubからEC2サーバへクローンします。デプロイできるIPアドレスを持ったEC2サーバー上でアプリケーションを動かすためです。

現状、EC2サーバにアプリケーションのコードをクローンしようとしても「permission denied」とエラーが出てしまいます。
これは、GitHubから見てこのEC2インスタンスが何者かわからないためです。

https://tech-master.s3.amazonaws.com/uploads/curriculums//d3bf10bbc2c2c2760fe34622bd3f8f60.png

EC2インスタンスからGitHubにアクセスするためには、作成したEC2インスタンスssh公開鍵をGitHubに登録する必要があります。
ssh鍵をGitHubに登録すると、GitHubはそれを認証に利用し、コードのクローンを許可してくれるようになります。

https://tech-master.s3.amazonaws.com/uploads/curriculums//4ceb5a3527c15a1ca97986837da096a9.png

 EC2サーバーのssh鍵のペアを作成し、GitHubssh鍵を登録しましょう

以下のコマンド入力して、EC2サーバのssh鍵ペアを作成しましょう

 
[ec2-user@ip-172-31-23-189 ~]$ ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ec2-user/.ssh/id_rsa.
Your public key has been saved in /home/ec2-user/.ssh/id_rsa.pub.
The key fingerprint is:
3a:8c:1d:d1:a9:22:c7:6e:6b:43:22:31:0f:ca:63:fa ec2-user@ip-172-31-23-189
The key's randomart image is:
+--[ RSA 4096]----+
|    +            |
| . . =           |
|  = . o .        |
| * o . o         |
|= *     S        |
|.* +     .       |
|  * +            |
| .E+ .           |
| .o              |
+-----------------+
 

次に、「catコマンド」で表示されたssh公開鍵の値をコピーします。

 catコマンド

「catコマンド」を実行することで、そのファイル(あるいは値)の具体的な内容をターミナル上で確認できます。

 ssh公開鍵の値を確認し、GitHubに登録しましょう

catコマンドで、公開鍵が含まれているファイルid_rsa.pubの中身をターミナル上に表示します。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 ~]$ cat ~/.ssh/id_rsa.pub

そして、以下のように表示される公開鍵の情報をすべて(「ssh-rsa」から「末尾の文字」まで)コピーします。

【例】ターミナル上における公開鍵の表示結果
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLwt......
# 表示された内容すべてをコピー

次に、コピーした公開鍵をGitHubに登録します。
まず、以下のリンクにアクセスしてください。
SSH鍵登録リンク

画面遷移後、右上にある「New SSH key」をクリックしましょう。

https://tech-master.s3.amazonaws.com/uploads/curriculums//6a0d48ec44a365c5abbe393dc552d8b8.png

次の画面では、公開鍵のタイトルを設定し、コピーした公開鍵を貼り付けましょう。入力ができたら、「Add SSH key」をクリックして公開鍵を保存します。

https://tech-master.s3.amazonaws.com/uploads/curriculums//29ffd520b7d15adb94ce13fe42c624f0.png

GitHubに鍵を登録できたら、ssh接続できるか以下のコマンドで確認してみましょう。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 ~]$ ssh -T git@github.com
Hi <Githubユーザー名>! You've successfully authenticated, but GitHub does not provide shell access.
 途中でこのまま続けるかどうか、「Yes/No」または「y/n」などの選択肢で聞かれることがあります。その場合は「Yes」または「y」などの「許容」を意味する入力をし、Enterキーを押下して進んでください。

「Permission denied (publickey).」と表示された場合は、ssh鍵の設定が間違っているので、再度作業を確認しましょう。

続いて、「アプリケーションサーバー」の導入と設定を行います。

 アプリケーションサーバ

アプリケーションサーバー」とは、ブラウザからの「リクエスト」を受け付けRailsアプリケーションを実際に動作させるソフトウェアのことです。

アプリケーションサーバーの設定をしよう

実は皆さんはすでにアプリケーションサーバを利用しています。それが、「rails sコマンド」です。

普段皆さんがローカル環境でRuby on Railsのアプリケーションの動作を確認する際、以下の手順を踏むと思います。

手順 実行内容
ターミナルで「rails sコマンド」を打つ
ブラウザで「localhost:3000」にアクセスする

①をせずに②を行なっても、アプリケーションの動作は確認できません。

この①の操作はまさに「アプリケーションサーバーの起動」を行なっています。

rails sコマンドを打つと「puma」と呼ばれるアプリケーションサーバーが起動しています。以下は、ローカルでrails sコマンドを実行した時の様子です。

【例】ローカルでアプリケーションサーバーを起動
#rails sコマンドでサーバを起動

$ rails s
=> Booting Puma
=> Rails 6.0.2.1 application starting in development 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 3.12.4 (ruby 2.6.5-p114), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop

4行目に「Booting Puma」と書かれています。これは「pumaを起動しています」ということです。rails sコマンドを打つことで、pumaというアプリケーションサーバが起動していることがわかりました。

また、localhost:3000とは「自身のPCを指すドメイン」のことです。

つまり、①、②の実行内容は「自身のPCをサーバに見立てアプリケーションサーバーを起動し、ブラウザから自身のPCにアクセスする」と言い換えることが出来ます。

アプリケーションサーバーが動いていれば、ブラウザからのリクエストを受け付けてRailsアプリケーションが動作します。

ということで、全世界に公開するEC2サーバー上でもアプリケーションサーバを動かす必要があります。

そのために必要なツールが「Unicorn」と呼ばれるものです。

 Unicorn

Unicorn」とは、全世界に公開されるサーバ上で良く利用されるアプリケーションサーバーです。rails sコマンドの代わりに「unicorn_railsコマンド」で起動することができます。

この後、EC2サーバにssh接続しUnicornを起動することで全世界からアクセスできるようにします。イメージとしては、以下の図のようになります。

https://tech-master.s3.amazonaws.com/uploads/curriculums//238665045a83e58cb58ea059d1558aa3.png

ここで、Unicornを理解するために必要な概念である「プロセス」についても押さえておきましょう。

 プロセス

「プロセス」とは、PC上で動くすべてのプログラムの実行時の単位です。ここで言うプログラムとは、ブラウザや音楽再生ソフト、ExcelといったGUIや、Rubyなどのスクリプト言語の実行などが含まれます。

プログラムが動いている数だけ、プロセスが存在しています。たとえばテキストエディタを起動する時、テキストエディタ用のプロセスが生み出されます。

それでは、実際にプロセスを確認しましょう。

 アクティビティモニタ

アクティビティモニタは、現在MacPC上で動いているプログラムの状況をモニタリングするアプリです。アクティビティモニタでプロセスを確認することができます。

プロセスを確認しましょう

command(⌘)を押しながらスペースを押して、Spotlight検索を行います。アクティビティと入力するだけでアクティビティモニタが表示されます。Enterキーを押下して、アクティビティモニタを起動しましょう。

https://tech-master.s3.amazonaws.com/uploads/curriculums//2f470bda2b6b005b346a39e857e541de.gif

以下が、アクティビティモニタを開いた画面です。

https://tech-master.s3.amazonaws.com/uploads/curriculums//126547c61ef6ab4c2c9292ee71c8b1f8.png

一番左上の「プロセス名」と言う列に注目してください。Google Chromeや、アクティビティモニタ自身も表示されています。
つまり、Google Chromeアクティビティモニタもプロセスであるということです。

Unicornなどのアプリケーションサーバを起動するとアプリケーションサーバのプロセスが生まれます。アプリケーションサーバのプロセスがあれば、リクエストを受け付けブラウザにレスポンスを返すことができます。

それでは、Unicornを利用する準備を行いましょう。

Unicornの設定をしよう

ここからは、実際にUnicornを使えるさまざまな設定をします。

 Unicornをインストールしましょう

まず、Gemfileのgroup :production do〜end内に内容を追記しましょう。

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

不要なGemをコメントアウトしましょう

Herokuで使用したrails_12factorのGemはコメントアウトをしてください。EC2ではログの保存場所が変わります。そのためrails_12factorがあると、うまくログが保存できなくなるためです。

Gemfile
group :production do
  # gem ‘rails_12factor’
  gem 'unicorn', '5.4.1'
end

編集したら「bundle install」しましょう。

ターミナル(ローカル)

続いては、ファイルの編集を行います。

unicorn.rb」を作成し、以下のように編集しましょう

 以下の作業は「masterブランチ」で作業しましょう。

「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

上記のファイルの中で、重要な設定とそれにまつわる概念について解説します。

 worker(ワーカー)

「worker」とは、分裂したUnicornの全プロセスのことです。プロセスを分裂させることで、リクエストに対してのレスポンスを高速にできます。後述するworker_processesという設定項目で、workerの数を決定します。

ブラウザなどからリクエストが来ると、UnicornのworkerがRailsアプリケーションを動かします。Railsは、リクエストの内容とルーティングを照らし合わせ最終的に適切なビュー(HTML)もしくはJSONをレスポンスします。レスポンスを受け取ったUnicornは、それをブラウザに返します。一連の動きはおよそ0.1 ~ 0.5秒程度で行われます。常にそれ以上のスピードでリクエストが頻発するようなアプリケーションだと、1つのworkerだけでは処理が追いつかず、レスポンスまで長い時間がかかってしまったり最悪サーバがストップしてしまいます。そんな時、worker_processesの数を 2,3,4と増やすことでアプリケーションからのレスポンスを早くできます。

その他の設定項目は以下の通りです。

設定項目 詳細
worker_processes リクエストを受け付けレスポンスを生成するworker(ワーカー)の数を決めます。
working_directory UnicornRailsのコードを動かす際、ルーティングなど実際に参照するファイルを探すディレクトリを指定します。
pid Unicornは、起動する際にプロセスidが書かれたファイルを生成します。その場所を指定します。
listen どのポート番号のリクエストを受け付けることにするかを決定します。今回は、3000番ポートを指定しています。

それでは、ファイルの編集内容をGitHubに反映させましょう。

 編集内容をリモートリポジトリに反映しましょう

ここまで編集できたら、リモートリポジトリに「commit→push」しましょう。

 別にブランチを切っている場合は、masterブランチにmergeしてから以下のコマンドを実行しましょう。

GitHubのリモートリポジトリに反映ができたら、ここまでのローカルの全内容をEC2に反映します。

 EC2にローカルの全内容を反映しましょう

まず、以下のコマンドを実行し、権限を付与しましょう。

ターミナル(EC2内で実行)
#mkdirコマンドで新たにディレクトリを作成
[ec2-user@ip-172-31-23-189 ~]$ sudo mkdir /var/www/

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

次に、GitHubから「リポジトリURL」を取得し、クローンします。
デプロイするアプリケーションのGitHubを開きましょう。緑色で「Code」と表示されているボタンをクリックして、URLをコピーします。

https://tech-master.s3.amazonaws.com/uploads/curriculums//6feba670334d1d4943502e1e3fd55acb.png

URLがコピーできたら、コードをクローンします。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/
[ec2-user@ip-172-31-23-189 www]$ git clone コピーしたURLを貼り付ける

上記の入力でエラーがでなければ、先に進みましょう。

本番環境での設定

ここまでで、アプリケーションのコードをEC2にクローンすることができました。続いて、サービスを公開するための設定を行なっていきます。

EC2の能力を拡張しよう

現状動かしているEC2のインスタンスではコンピューターの能力が足りず、Gemのインストール時などにエラーが発生する可能性があります。具体的には、コンピューターの処理能力に関係するメモリというものが足りません。これは、無料で動かせるインスタンスの限界であるため仕方ありません。

そこで、今後の設定を行う前に「Swapファイル」というメモリを増強する処理を行います。

Swap(スワップ)ファイル

「Swapファイル」とは、メモリの容量を一時的に増やすために準備されるファイルのことです。コンピューターが処理を行う際、メモリと呼ばれる場所に処理内容が一時的に記録されます。メモリは容量が決まっており、容量を超えてしまうとエラーで処理が止まってしまいます。

EC2はデフォルトではSwapファイルを用意していないため、これを準備することでメモリ不足の処理エラーを防ぎます。

Swapファイルの領域を広げましょう

まずは、EC2にssh接続をしてホームディレクトリに移動します。

ターミナル(EC2内で実行)
# ホームディレクトリに移動
[ec2-user@ip-172-31-25-189 ~]$ cd

続いて、以下のコマンドを順に実行します。

ターミナル(EC2内で実行)
# 処理に時間がかかる可能性があるコマンドです

[ec2-user@ip-172-31-25-189 ~]$ sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512

# しばらく待って、以下のように表示されれば成功です
512+0 レコード入力
512+0 レコード出力
536870912 バイト (537 MB) コピーされました、 7.35077 秒、 73.0 MB/秒
ターミナル(EC2内で実行)
[ec2-user@ip-172-31-25-189 ~]$ sudo chmod 600 /swapfile1
ターミナル(EC2内で実行)
[ec2-user@ip-172-31-25-189 ~]$ sudo mkswap /swapfile1

# 以下のように表示されれば成功
スワップ空間バージョン1を設定します、サイズ = 524284 KiB
ラベルはありません, UUID=74a961ba-7a33-4c18-b1cd-9779bcda8ab1
ターミナル(EC2内で実行)
[ec2-user@ip-172-31-25-189 ~]$ sudo swapon /swapfile1
ターミナル(EC2内で実行)
[ec2-user@ip-172-31-25-189 ~]$ sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab'

これで、Swapファイルの領域を確保することができました。

EC2内でgemをインストールしよう

EC2にクローンしたアプリケーションを起動するために必要なgemを以下のコマンドでインストールしましょう。

 必要なgemをインストールしましょう

ターミナル(EC2内で実行)
# クローンしたディレクトリに移動
[ec2-user@ip-172-31-23-189 www]$ cd  /var/www/開発中のアプリケーション

# rubyのバージョンを確認
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
 「ruby 2.6.5 ...」となっていれば成功です。そうでない場合は、もともと用意されているRubyが利用されているので、Rubyのインストールが成功しているか確認してください。

次に、本番環境でgemを管理するためのbundlerをインストールします。

まずは、ローカルで開発してきたアプリケーションでどのバージョンのbundlerが使われていたのか確認します。

 実行場所は「ローカル」です。
ターミナル(ローカル)
# 開発中のアプリケーションのディレクトリで実行

% bundler -v
Bundler version 2.1.4
 開発環境によってバージョンは異なります。

ローカルと同じバージョンのbundlerをEC2側にも導入します。上記の場合では「bundler 2.1.4」のバージョンを導入してbundle installを実行します。

 実行場所は「EC2内」です。
ターミナル(EC2内で実行)
# 「2.1.4」の箇所は、ローカルで確認したbundlerのバージョンを導入します
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ gem install bundler -v 2.1.4

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

環境変数を設定しよう

データベースのパスワードなどセキュリティのためにGitHubにアップロードすることができない情報は「環境変数」を利用して設定します。

環境変数は、Railsからは「ENV['<環境変数名>']」という記述でその値を利用できます。今回は「SECRET_KEY_BASE」という環境変数を指定します。

 secret_key_base

「secret_key_base」とは、Cookieの暗号化に用いられる文字列です。Railsアプリケーションを動作させる際は必ず用意する必要があります。また、外部に漏らしてはいけない値であるため、こちらも環境変数から参照します。

それでは、secret_key_baseを環境変数に設定しましょう。

 secret_key_baseを作成しましょう

まずは、以下のコマンドでsecret_key_baseを作成します。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rake secret
69619d9a75b78f2e1c87ec5e07541b42f23efeb6a54e97da3723de06fe74af29d5718adff77d2b04b2805d3a1e143fa61baacfbf4ca2c6fcc608cff8d5a28e8d
 表示された英数の羅列はすべてメモアプリなどに控えておきましょう。

次に、EC2内に環境変数を設定しましょう。

環境変数は「/etc/environment」というファイルに保存します。環境変数の書き込みにはvimコマンドを使用しましょう。その際、「sudo」というオプションを使います。

 sudo

「sudo」とは、「全部の権限を持った上でコマンドを実行する」という役割のオプションです。「/etc以下のファイル」は強い権限がないと書き込み・保存ができないため、コマンドの頭に「sudo」をつけています。

環境変数を設定しましょう

コマンドを実行してsecret_key_baseを環境変数に設定しましょう。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 ~]$ sudo vim /etc/environment

https://tech-master.s3.amazonaws.com/uploads/curriculums//64fb579a7ae6073b36bb83836fe989d9.png

上記の様な画面になれば、まず「i」と打ち込んで入力モードに切り替えます。その後下記の記述を打ち込みます。

 「=」の前後にスペースは入れません。
/etc/environment
#前章で設定したデータベースのrootユーザーのパスワードを入力
DATABASE_PASSWORD='データベースのrootユーザーのパスワード'
SECRET_KEY_BASE='さきほど作成したsecret_key_base'

# 「Heroku上で投稿した画像をS3へ保存する方法を学ぼう」でダウンロードしたCSVファイルを参考に値を入力
AWS_ACCESS_KEY_ID='ここにCSVファイルのAccess key IDの値をコピー'
AWS_SECRET_ACCESS_KEY='ここにCSVファイルのSecret access keyの値をコピー'

# Basic認証で設定したユーザー名とパスワードを入力
BASIC_AUTH_USER='設定したユーザー名'
BASIC_AUTH_PASSWORD='設定したパスワード'

入力を終えたら「escキー」→「:wq」の順で実行し、保存しましょう。

環境変数を反映させましょう

設定した環境変数を反映させるために、一度本番環境をログアウトします。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 ~]$ exit
logout
Connection to 52.xx.xx.xx closed.

次は、いま設定した環境変数がしっかり反映されているか確認します。
exitでログアウトするので、以下のコマンドで再度EC2に接続します。

ターミナル(ローカル)
$ ssh -i [ダウンロードした鍵の名前].pem ec2-user@[作成したEC2インスタンスと紐付けたElastic IP]

接続し直したら、「envコマンド」と「grepコマンド」を組み合わせて、さきほど設定した環境変数が適用されているか確認します。

 envコマンド

「envコマンド」とは、設定されている環境変数を表示するためのコマンドです。envは「environment(環境)」の略称です。このコマンドで全環境変数を表示できます。

 grepコマンド

grepコマンド」は、環境変数などを検索するときに使います。使い方は「grep (検索対象)」となります。

それでは上記のコマンドを使って確認しましょう。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 ~]$ env | grep SECRET_KEY_BASE
SECRET_KEY_BASE='secret_key_base'

[ec2-user@ip-172-31-23-189 ~]$ env | grep DATABASE_PASSWORD
DATABASE_PASSWORD='データベースのrootユーザーのパスワード'

[ec2-user@ip-172-31-23-189 ~]$ env | grep AWS_SECRET_ACCESS_KEY
AWS_SECRET_ACCESS_KEY='Secret access key'

[ec2-user@ip-172-31-23-189 ~]$ env | grep AWS_ACCESS_KEY_ID
AWS_ACCESS_KEY_ID='Access key ID'

[ec2-user@ip-172-31-23-189 ~]$ env | grep BASIC_AUTH_USER
BASIC_AUTH_USER='設定したユーザー名'

[ec2-user@ip-172-31-23-189 ~]$ env | grep BASIC_AUTH_PASSWORD
BASIC_AUTH_PASSWORD='設定したパスワード'

ポートを解放しよう

立ち上げたばかりのEC2インスタンスsshでアクセスすることはできますが、HTTPなどの他の通信方法では一切つながらないようになっています。そのため、サーバーとして利用するEC2インスタンスは事前にHTTPがつながるように「ポート」を開放する必要があります。
さきほど、config/unicorn.rb内に「listen 3000」と記述しましたが、これは「Railsのサーバを3000番ポートで起動する」ということを意味するのでした。

ポートの設定をするためには、EC2の「セキュリティグループ」という設定を変更する必要があります。

 セキュリティグループ

「セキュリティグループ」とは、EC2サーバが属するまとまりのようなもので、複数のEC2インスタンスのネットワーク設定を一括で行うためのものです。

それでは、セキュリティグループのポートを設定しましょう

 セキュリティグループのポートを設定しましょう

まず、EC2インスタンス一覧画面から、対象のインスタンスを選択し、「セキュリティ」のタブを開きます。次に、「セキュリティグループ」のリンク(図中では「launch-wizard-1」)をクリックしましょう。

https://tech-master.s3.amazonaws.com/uploads/curriculums//37abfe04c03a0adb453b5b03b139aeba.png

すると、インスタンスの属するセキュリティグループの設定画面に移動するので、「インバウンド」タブの中の「編集」をクリックします。

「アウトバウンド」と間違えないように注意しましょう。

https://tech-master.s3.amazonaws.com/uploads/curriculums//84bf1618a1238eaa5a90811352ec0db6.png

ページが切り替わるので、「インバウンドルールを編集」をクリックし、以下の通りに設定しましょう。
ページ遷移後、「ルールを追加」をクリックして下記に編集しましょう。

タイプ プロトコル ポート範囲 送信元
カスタムTCP TCP 3000 カスタム/0.0.0.0/0

「0.0.0.0」は「すべてのアクセスを許可する」という意味です。

https://tech-master.s3.amazonaws.com/uploads/curriculums//f9cadcecaafaa68bdd1df386dfb5272a.png

設定後、「ルールを保存」をクリックしましょう。

ポートの開放は以上です。

Railsを起動する

本番環境でRailsを起動させよう

いよいよ本番環境でRailsを起動します。
本番環境でRailsを起動するには「unicorn_railsコマンド」を使います。
それでは早速、Railsを起動しましょう。

 以下の手順で、本番環境でRailsを起動させましょう

まず、VSCodeで「database.yml」の本番環境の設定を編集しましょう

本番環境のmysqlの設定に合わせるため、ローカルのdatabase.ymlを以下のように編集してください。

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

次に、編集を「commit→push」しましょう。
リモートリポジトリが更新されたため、サーバ上のアプリケーションにも反映させましょう。

 別にブランチを切っている場合は、masterブランチにmergeしてから以下のコマンドを実行しましょう。

次は、GitHubの内容をEC2に反映させる作業です。
以下のコマンドを実行しましょう。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 <リポジトリ名>] git pull origin master

次は、EC2内でデータベースを作成するのですが、「RAILS_ENV=production」というオプションがつきます。

 RAILS_ENV=production

RAILS_ENV=production」とは、本番環境でコマンド実行する時につくオプションです。
実行しようとしているコマンドは、「RAILSのENV(環境)がproduction(本番環境)ですよ」という意味です。

それでは以下のコマンドを順に実行しましょう。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails db:create RAILS_ENV=production
Created database '<データベース名>'
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails db:migrate RAILS_ENV=production
 
 もしここで「Mysql2::Error: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock'」というエラーが起こった場合、データベースが起動していない可能性があります。

「sudo systemctl start mariadb」というコマンドをターミナルから打ち込み、mysqlの起動を試してみましょう。

ここまでできたら、Railsを起動しましょう。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/[リポジトリ]
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D

 アセットファイル

「アセットファイル」とは、画像・CSSJavaScript等を管理しているファイルです。このアセットファイルを圧縮し、そのデータを転送する処理を「コンパイル」と言います。この作業を行わないと、本番環境でCSSが反映されずにビューが崩れてしまったり、エラーでブラウザが表示されない、などの問題が生じてしまいます。
開発中はアクセス毎にアセットファイルを自動的にコンパイルする仕組みが備わっていますが、本番モードのときにはパフォーマンスを重視するため、アクセス毎にコンパイルが実行されないようになっているのです。

アセットファイルをコンパイルしよう

それでは、アセットファイルをコンパイルします。

以下の手順で、アセットファイルをコンパイルしましょう

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails assets:precompile RAILS_ENV=production

ここまで終えたら再度Railsを起動させたいのですが、すでにサーバーは立ち上がっています。
そこで、「Railsを再起動する方法」を学びましょう。

Railsを再起動しよう

本番環境でRailsを再起動する場合、ローカルと少しやり方が異なります。
以下の表でローカルでの作業時と比較しましょう。

手順 ローカルでの作業 本番環境での作業
「Ctrl」+「c」でサーバーを止める ・プロセスを確認する
・プロセスを止める
rails s」を実行する unicorn_railsコマンド」を実行する

それでは、実際に操作しましょう。

 以下の手順で、本番環境のRailsを再起動しましょう

まず、「Unicornのプロセス」を確認します。
ターミナルからプロセスを確認するには「psコマンド」を利用します。

psコマンド

「psコマンド」とは、現在動いているプロセスを確認するためのコマンドです。

それでは「psコマンド」を実行し、Unicornのプロセスを確認しましょう

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
...

すると、以下のようにプロセスが表示されるはずです。

```bash:ターミナル
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

大事なのは左から2番目の列です。ここに表示されるのがプロセスのid(PIDと言う)になります。
unicorn_rails master」と表示されているプロセスがUnicornのプロセス本体です。この時のプロセスidは「17877」となっています。

 プロセスid

プロセスidは、プロセスを識別するための一意の数字です。PIDがあることで、あるプログラムから別のプロセスを指定して操作したり、プロセスからプログラムを停止したりできます。

先程確認したアクティビティモニタの真ん中あたりにある「PID(プロセスアイディー)」もプロセスidです。

https://tech-master.s3.amazonaws.com/uploads/curriculums//e626bddb165744b6715f1d256d064fe3.png

killコマンド

killコマンドは、現在動いているプロセスを停止させるためのコマンドです。

それでは、以下のコマンドを実行してUnicornのプロセスをKillしましょう。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのプロセスid>

実行したプロセスを再度表示させ、終了できていることを確認しましょう。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
...
ec2-user 17911  0.0  0.2 110532  2180 pts/0    S+   02:05   0:00 grep --color=auto unicorn

実行結果が上記のようになっていれば、Unicornの停止が完了です。

 プロセスが1つだけ残っているのは、「ps aux | grep unicorn」コマンドのプロセスです。このコマンドが「unicornに関するすべてのプロセスを表示する」という役割なので、「unicornのプロセスを検索ために使った ”ps aux | grep unicorn” もカウントされている」ということになります。
 「master」のプロセスをkillすると、「worker」のプロセスも一緒にkillされます。

最後に、Railsを再起動するコマンドを実行しましょう。
今回はコマンドの先頭に「RAILS_SERVE_STATIC_FILES=1」というオプションをつけます。

 RAILS_SERVE_STATIC_FILES=1

RAILS_SERVE_STATIC_FILES=1」は、Railsコンパイルされたアセットを見つけられるように指定する役割があります。

それでは、以下のコマンドを実行しましょう。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D

ブラウザで http://<Elastic IP>:3000/ にアクセスして、サイトが正常に表示されているか確認してみましょう。

 接続時、<Elastic IP>の<>は不要です。

Railsの起動がうまくできなかった時

Railsが起動しない」「ブラウザで確認するとエラーが表示されている」などの問題がある場合、まずは「エラーログ」を確認する必要があります。

 エラーログ

「エラーログ」とは、エラーの詳細が書かれているログ(記録場所)のことです。

エラーログを確認しよう

ここでは、2つのエラーログ確認方法を学びましょう。

 ターミナルで「unicorn_rails」が起動しない時の対処法を学びましょう

ターミナル(EC2サーバ)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
master failed to start, check stderr log for details

このように、unicorn_railsを実行した際に「master failed to start, check stderr log for details」と出た場合、unicornのエラーログを確認する必要があります。

「check stderr log for details」というのは、「詳細(detail)はstderr logを確認(check)しましょう」という意味です。
実は、unicornでエラー起きた場合、エラーログの場所はすでにご自身で設定しています。
以下を確認しましょう。

config/unicorn.rb
(省略)

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

(省略)

また、ログファイルを見る際に「lessコマンド」というものを使います。

 lessコマンド

「lessコマンド」を使うと、ファイルの中身を確認できます。「catコマンド」も同様の役割をします。

それでunicornのエラーログを確認しましょう。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ less log/unicorn.stderr.log
I, [2016-12-21T04:01:19.135154 #18813]  INFO -- : Refreshing Gem list
I, [2016-12-21T04:01:20.732521 #18813]  INFO -- : listening on addr=0.0.0.0:3000 fd=10
E, [2016-12-21T04:01:20.734067 #18813] Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
/var/www/furima/shared/bundle/ruby/2.6.0/gems/mysql2-0.5.3/lib/mysql2/client.rb:90:in `connect'
/var/www/furima/shared/bundle/ruby/2.6.0/gems/mysql2-0.5.3/lib/mysql2/client.rb:90:in `initialize'
/var/www/furima/shared/bundle/ruby/2.6.0/gems/activerecord-6.0.2.1/lib/active_record/connection_adapters/mysql2_adapter.rb:24:in `new'
/var/www/furima/shared/bundle/ruby/2.6.0/gems/activerecord-6.0.2.1/lib/active_record/connection_adapters/mysql2_adapter.rb:24:in `mysql2_connection'
/var/www/furima/shared/bundle/ruby/2.6.0/gems/activerecord-6.0.2.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:889:in `new_connection'
 
 ログファイルは「一番下から最新のログ」が表示されます。”「shiftキー」+「G」”を実行すると、一番下まで一瞬で移動できます。

この中からエラー文を探しましょう。

ブラウザに「We’re sorry, but 〜」と表示されている時の対処法を学びましょう

https://tech-master.s3.amazonaws.com/uploads/curriculums//5181f06d639db4cabb767004aa830ad4.png

このような表示が出ている場合、まずは「production.log」を確認する必要があります。

 production.log

「production.log」とは、サーバーログを記録する場所で、いわば「EC2内での出来事を記録している場所」です。ローカルにおいてrails sコマンドでアプリケーションを実行したときも、さまざまなログが表示されます。それと同様の役割です。

それでは以下のコマンドを実行しましょう。

ターミナル(EC2内で実行)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ less log/production.log

(production.logの表示)
 ログファイルは「一番下から最新のログ」が表示されます。”「shiftキー」+「G」”を実行すると、一番下まで一瞬で移動できます。

この中からエラー文を探しましょう。

また、もう少しログを見やすく確認できるツールとして「tail -fコマンド」というものもあります。

tail -fコマンド

「tail -fコマンド」とは、最新のログを10行分だけ表示してくれるコマンドです。

下図は、実際にコマンドを実行した時の様子です。

https://tech-master.s3.amazonaws.com/uploads/curriculums//1565f913a4175b96d537f77126548365.png