目的
AWS
のサーバーを利用し、Railsで作成したアプリを公開する。
開発環境
macOS: Big Sur
Rubyバージョン: 2.6.5
Railsバージョン: 6.0.0
前提
-
データベース
の設定が完了している。【AWS】EC2でのデプロイ(データベースの設定)
手順
- はじめに
- EC2サーバーssh鍵ペアの作成
- GitHubにssh鍵を登録
- Unicornの設定
- 本番環境の設定
- EC2内でgemをインストール
- 環境変数の設定
- ポートの解放
- Railsの起動
- アセットファイルのコンパイル
- Railsの再起動
- ターミナルで「unicorn_rails」が起動しない時の対処法
- ブラウザに「We’re sorry, but 〜」と表示されている時の対処法
はじめに
今回は本番環境でRailsを起動していきます!
EC2サーバーssh鍵ペアの作成
それでは早速始めていきます!
まず、デプロイできるIPアドレスを持ったEC2サーバー上でアプリを動かすために、アプリのコードをGitHubからEC2サーバへクローンします。
EC2インスタンスからGitHubにアクセスするためには、作成したEC2インスタンスのssh公開鍵をGitHubに登録する必要があります。
ssh鍵をGitHubに登録すると、GitHubはそれを認証に利用し、コードのクローンを許可してくれるようになります。
以下のコマンド入力して、EC2サーバのssh鍵ペアを作成します。
途中で「passphrase」など3段階ほど入力を求められることがありますが、すべて何も入力せずにEnterキーを押して進んでください。
[ec2-user@ip-172-31-23-189 ~]$ ssh-keygen -t rsa -b 4096
これで作成されました!
GitHubにssh鍵を登録
続いて、catコマンド
で、公開鍵が含まれているファイルid_rsa.pub
の中身をターミナル上に表示します。
[ec2-user@ip-172-31-23-189 ~]$ cat ~/.ssh/id_rsa.pub
そして、表示された公開鍵の情報をすべて(「ssh-rsa」から「末尾の文字」まで)コピーします。
次に、コピーした公開鍵をGitHubに登録します。以下のリンクにアクセスしてください。
SSH鍵登録ページ
画面遷移後、右上にある「New SSH key」をクリックし、公開鍵のタイトルを設定してコピーした公開鍵を貼り付けます。
入力ができたら、「Add SSH key」をクリックして公開鍵を保存します。
GitHubに鍵を登録できたら、ssh接続できるか以下のコマンドで確認してみます!
[ec2-user@ip-172-31-23-189 ~]$ ssh -T git@github.com
Unicornの設定
次に、アプリケーションサーバー
の導入と設定を行います。
全世界に公開するEC2サーバー上でアプリケーションサーバを動かすためにはUnicorn
というツールが必要です。
Unicorn
とは、全世界に公開されるサーバ上で良く利用されるアプリケーションサーバーです。rails sコマンドの代わりにunicorn_railsコマンド
で起動することができます。
それではまずUnicorn
のインストールを行います!
Gemfileのgroup :production do〜end内に内容を追記します。
group :production do
gem 'unicorn', '5.4.1'
end
% bundle install
続いて「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
とは、分裂したUnicornの全プロセスのことです。プロセスを分裂させることで、リクエストに対してのレスポンスを高速にできます。
ブラウザなどからリクエストが来ると、Unicorn
のworker
がRailsアプリを動かします。
Railsは、リクエストの内容とルーティングを照らし合わせ最終的に適切なビュー(HTML)もしくはJSONをレスポンスします。
レスポンスを受け取ったUnicorn
は、それをブラウザに返します。一連の動きはおよそ0.1 ~ 0.5秒程度で行われます。
常にそれ以上のスピードでリクエストが頻発するようなアプリケーションだと、1つのworker
だけでは処理が追いつかず、レスポンスまで長い時間がかかってしまったり最悪サーバがストップしてしまいます。
そんな時、worker_processes
の数を 2,3,4と増やすことでアプリケーションからのレスポンスを早くできます。
設定項目 | 詳細 |
---|---|
worker_processes | リクエストを受け付けレスポンスを生成するworker(ワーカー)の数 |
working_directory | UnicornがRailsのコードを動かす際、ルーティングなど実際に参照するファイルを探すディレクトリを指定 |
pid | Unicornは、起動する際にプロセスidが書かれたファイルを生成します。その場所を指定 |
listen | どのポート番号のリクエストを受け付けることにするかを決定 |
編集できたら、リモートリポジトリに「commit→push」します!
その後下記コマンドを実行し、権限を付与します。
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をコピーします。
そして、下記コマンドでコードをクローンします。
[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/
[ec2-user@ip-172-31-23-189 www]$ git clone コピーしたURLを貼り付ける
これでクローンできました!
本番環境の設定
ここまでで、アプリケーションのコードをEC2にクローンすることができました。続いて、サービスを公開するための設定を行なっていきます!
現状動かしているEC2のインスタンスではコンピューターの能力が足りず、Gemのインストール時などにエラーが発生する可能性があります。具体的には、コンピューターの処理能力に関係するメモリが足りません。これは、無料で動かせるインスタンスの限界であるため仕方ありません。
そこで、今後の設定を行う前にSwapファイル
というメモリを増強する処理を行います。
Swapファイル
とは、メモリの容量を一時的に増やすために準備されるファイルのことです。コンピューターが処理を行う際、メモリと呼ばれる場所に処理内容が一時的に記録されます。メモリは容量が決まっており、容量を超えてしまうとエラーで処理が止まってしまいます。
EC2はデフォルトではSwapファイルを用意していないため、これを準備することでメモリ不足の処理エラーを防ぎます。
まずは、EC2にssh接続をしてホームディレクトリに移動します。
[ec2-user@ip-172-31-25-189 ~]$ cd
続いて、以下のコマンドを順に実行します。
[ec2-user@ip-172-31-25-189 ~]$ sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512
[ec2-user@ip-172-31-25-189 ~]$ sudo chmod 600 /swapfile1
[ec2-user@ip-172-31-25-189 ~]$ sudo mkswap /swapfile1
[ec2-user@ip-172-31-25-189 ~]$ sudo swapon /swapfile1
[ec2-user@ip-172-31-25-189 ~]$ sudo sh -c 'echo "/swapfile1 none swap sw 0 0" >> /etc/fstab'
これで、Swapファイルの領域を確保することができました!
EC2内でgemをインストール
EC2にクローンしたアプリケーションを起動するために必要なgemをインストールしていきます!
クローンしたディレクトリに移動
[ec2-user@ip-172-31-23-189 www]$ cd /var/www/開発中のアプリケーション
rubyのバージョンを確認
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ruby -v
次に、本番環境でgemを管理するためのbundlerをインストールします。
まずは、ローカルで開発してきたアプリケーションでどのバージョンのbundlerが使われていたのか確認します。
% bundler -v
ローカルと同じバージョンのbundlerをEC2側にも導入します。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ gem install bundler -v 2.1.4
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle install
環境変数の設定
次に環境変数の設定です。
Cookieの暗号化に用いられる文字列のsecret_key_base
も環境変数に設定していきます。
まず以下のコマンドでsecret_key_baseを作成します。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rake secret
表示された英数の羅列はすべてメモアプリなどに控えておきます。
続いて環境変数の設定です。
[ec2-user@ip-172-31-23-189 ~]$ sudo vim /etc/environment
コマンド入力後、「i」
を入力し、入力モードに切り替えます。
その後下記の記述を打ち込みます。
#データベースのrootユーザーのパスワードを入力
DATABASE_PASSWORD='データベースのrootユーザーのパスワード'
SECRET_KEY_BASE='さきほど作成したsecret_key_base'
# 「S3」でダウンロードしたCSVファイルを参考に値を入力
AWS_ACCESS_KEY_ID='ここにCSVファイルのAccess key IDの値をコピー'
AWS_SECRET_ACCESS_KEY='ここにCSVファイルのSecret access keyの値をコピー'
設定した環境変数を反映させるために、一度本番環境をログアウトします。
[ec2-user@ip-172-31-23-189 ~]$ exit
次に、いま設定した環境変数がしっかり反映されているか確認します。
$ ssh -i [ダウンロードした鍵の名前].pem ec2-user@[作成したEC2インスタンスと紐付けたElastic IP]
ログイン後、下記コマンドで確認します。
[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インスタンスはsshでアクセスすることはできますが、HTTPなどの他の通信方法では一切つながらないようになっています。
そのため、サーバーとして利用するEC2インスタンスは事前にHTTPがつながるように「ポート」を開放する必要があります。
まず、EC2インスタンス一覧画面から、対象のインスタンスを選択し、「セキュリティ」のタブを開きます。次に、「セキュリティグループ」のリンクをクリックします。
インスタンスの属するセキュリティグループの設定画面に移動するので、「インバウンド」タブの中の「編集」をクリックします。
ページが切り替わるので、「インバウンドルールを編集」をクリックし、ポート範囲「3000」
を追加します。
設定後、「ルールを保存」をクリックします。
これでポートの開放は以上です。
Railsの起動
ここから、いよいよ本番環境でRailsを起動します。
本番環境でRailsを起動するにはunicorn_railsコマンド
を使います。
まず、VSCodeでdatabase.yml
の本番環境の設定を編集します。
本番環境のmysqlの設定に合わせるため、ローカルのdatabase.yml
を以下のように編集してください。
production:
<<: *default
database:(※こちらは編集しないでください)
username: root
password: <%= ENV['DATABASE_PASSWORD'] %>
socket: /var/lib/mysql/mysql.sock
次に、編集を「commit→push」しましょう。
リモートリポジトリが更新されたため、サーバ上のアプリケーションにも反映させます。
次は、GitHubの内容をEC2に反映させる作業です。
以下のコマンドを実行してください。
[ec2-user@ip-172-31-23-189 <リポジトリ名>] git pull origin master
次は、EC2内でデータベースを作成するのですが、RAILS_ENV=production
というオプションがつきます。
RAILS_ENV=production
とは、本番環境でコマンド実行する時につくオプションです。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails db:create RAILS_ENV=production
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails db:migrate RAILS_ENV=production
ここまでできたら、Railsを起動します。
[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
アセットファイルのコンパイル
「アセットファイル」とは、画像・CSS・JavaScript等を管理しているファイルです。このアセットファイルを圧縮し、そのデータを転送する処理を「コンパイル」と言います。この作業を行わないと、本番環境でCSSが反映されずにビューが崩れてしまったり、エラーでブラウザが表示されない、などの問題が生じてしまいます。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails assets:precompile RAILS_ENV=production
ここまで終えたら再度Railsを起動させたいのですが、すでにサーバーは立ち上がっています。
そこで、Railsを再起動します!
Railsの再起動
まず、Unicornのプロセス
を確認します。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ 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
大事なのは左から2番目の列です。ここに表示されるのがプロセスのid(PIDと言う)になります。
「unicorn_rails master」と表示されているプロセスがUnicornのプロセス本体です。この時のプロセスidは「17877」となっています。
それでは、以下のコマンドを実行してUnicornのプロセスをKillしましょう。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのプロセスid>
実行したプロセスを再度表示させ、終了できていることを確認しましょう。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
最後に、Railsを再起動するコマンドを実行しましょう。
今回はコマンドの先頭にRAILS_SERVE_STATIC_FILES=1
というオプションをつけます。
RAILS_SERVE_STATIC_FILES=1
は、Railsがコンパイルされたアセットを見つけられるように指定する役割があります。
[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/ にアクセスして、サイトが正常に表示されているか確認してみましょう!
ターミナルで「unicorn_rails」が起動しない時の対処法
「Railsが起動しない」「ブラウザで確認するとエラーが表示されている」などの問題がある場合、まずは「エラーログ」を確認する必要があります。
[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のエラーログを確認する必要があります。
それでunicornのエラーログを確認してみます!
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ less log/unicorn.stderr.log
ログファイルは「一番下から最新のログ」が表示されます。「shiftキー」+「G」
を実行すると、一番下まで一瞬で移動できます。
ブラウザに「We’re sorry, but 〜」と表示されている時の対処法
このような表示が出ている場合、まずはproduction.log
を確認する必要があります。
production.log
とは、サーバーログを記録する場所で、EC2内での出来事を記録している場所です。
以下のコマンドを実行します。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ less log/production.log
ログファイルは「一番下から最新のログ」が表示されます。「shiftキー」+「G」
を実行すると、一番下まで一瞬で移動できます。
最後に
以上で、EC2のRails起動は完了です。
次回はWebサーバーの設定を行っていきます。【AWS】EC2でのデプロイ(Webサーバーの設定)
では。