AWSを用いたデプロイの流れ(2)

甘党エンジニアのkanjiです。

前回に引き続き、AWSを用いたデプロイ・本番環境の構築の流れついて順を追って書いていく。

第1弾では「AWSのアカウント作成」から「データベースの設定」までをまとめた。

AWSを用いたデプロイの流れ(1)

今回は「開発したアプリケーションを全世界に公開(デプロイ)する手順」を設定する所までがゴールである。

GithubにSSH鍵を登録する

EC2インスタンスからGithubにアクセスするために、作成したEC2インスタンスのSSH公開鍵をGithubに登録する必要がある。

GitHubに公開鍵を登録することで身分提示(私は〇〇のEC2インスタンスです)となり、コードのクローンを許可してくれるようになる。

まずは以下のコマンド入力して、EC2サーバのSSH鍵ペアを作成する。

※途中で 「passphrase」 というものの入力を求めらるが、空のままで大丈夫。

[ec2-user@ip-555-432-111 ~]$ 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              |
+-----------------+

次に以下コマンドで生成されたSSH公開鍵を表示し、値(2行目以下)をコピーする。

[ec2-user@ip-555-432-111 ~]$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2E..............

以下GitHubのURLにアクセスし、先程catコマンドで表示させた公開鍵を登録する。

https://github.com/settings/keys

1.Title:ここは何でもOK

2.Key:公開鍵を貼り付ける

3.「Add SSH Key」を押して保存

Githubに鍵を登録できたら、以下のコマンドでSSH接続できるか確認。

下記の表示がされていればOK

[ec2-user@ip-555-432-111 ~]$ ssh -T git@github.com
Hi <Githubユーザー名>/<リポジトリ名>! You've successfully authenticated, but GitHub does not provide shell access.

アプリケーションサーバの設定

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

全世界からアクセスできるように設定するために、unicorn_railsコマンドで起動する。

Unicorn
全世界に公開されるサーバ上で良く利用されるアプリケーションサーバ

まずはUnicornをインストールするため、Gemfileを下記のように編集

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

変更できたらファイルをコミットし、Githubにpushする。

ブランチを切っている場合は、masterブランチにmergeを行う。

続いて、Unicornの設定を済ませたコードをEC2インスタンスにクローンする。

以下のコマンドを入力して、ディレクトリを作成。ディレクトリ内にアプリケーションを設置する。

(※必ずしもこの場所じゃなくてOK)

#mkdirコマンドで新たにディレクトリを作成
[ec2-user@ip-555-432-111 ~]$ sudo mkdir /var/www/

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

完了したら、Githubから「リポジトリURL」を取得。
取得した「リポジトリURL」を使って、コードをクローンする。

[ec2-user@ip-555-432-111 ~]$ cd /var/www/
[ec2-user@ip-555-432-111 www]$ git clone https://github.com/<リポジトリ名>.git

本番環境での設定

アプリケーションのコードをEC2サーバにクローン出来たので、サービスを公開するための設定を行っていく。

まずはローカルのアプリでbundlerのバージョンを確認する。

#ローカルのアプリのディレクトリで以下を実行
$ bundler -v
Bundler version 2.0.2
# 開発環境によってバージョンは異なります。

開発環境で仕様しているbundlerのバージョンがわかった後は、同じバージョンのものをEC2サーバ側にも導入する。

bundlerをインストールする

※上記の場合では、bundler 2.0.2のバージョンを導入して bundle install を実行。

[ec2-user@ip-555-432-111 <リポジトリ名>]$ gem install bundler -v 2.0.2
# ローカルで確認したbundlerのバージョンを導入する
[ec2-user@ip-555-432-111 <リポジトリ名>]$ bundle install

環境変数の設定

データベースのパスワードなどGithubに公開したくない情報は、環境変数を利用して設定する。

環境変数は、Railsからは ENV[’<環境変数名>’] という記述でその値を利用することができる。

例えば <%= ENV[“SECRET_KEY_BASE”] %> と書かれている部分は、 SECRET_KEY_BASE という環境変数の値になる。

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

以下のコマンドを打ち、secret_key_baseを生成・コピーする。

[ec2-user@ip-555-432-111 <リポジトリ名>]$ rake secret
37158d8a7ea4i55bf2e1c87ec5e04341f42f23eba8e54e97da54813ab06dc89af29d5718eacc45d2b90b3511d3e1c143fc61baacfbf4ca2c6fea608cbc8a4a35e8a

このsecret_key_baseを、EC2インスタンスに設定する。

今回は/etc/environmentというファイルに保存することで、サーバ全体に適用される。
環境変数の書き込みはvimコマンドを使用して行う。

以下のコマンドを打ち、環境変数を設定する。

[ec2-user@ip-555-432-111 〜]$ sudo vim /etc/environment

vimの画面になれば、「i」と打ち込んで入力モードに切り替えた後、下記の記述を打ち込む。

#前章で設定したMySQLのrootユーザーのパスワードを入力
DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'
SECRET_KEY_BASE='先程コピーしたsecret_key_base'
注意
=の前後にスペースを入れないこと。

書き込みができたら 「esc(エスケープキー)→:wq」と入力して内容を保存し、保存できたら環境変数を適用するために一旦ログアウトする。

[ec2-user@ip-555-432-111 〜]$ exit
logout
Connection to 52.xx.xx.xx closed.

ログアウトした後は再度SSHし直し、env というコマンドと grep を組み合わせて、先程設定した環境変数が適用されているか確認する。

$ ssh -i [ダウンロードした鍵の名前].pem ec2-user@[作成したEC2インスタンスと紐付けたElastic IP]
(ダウンロードした鍵を用いて、ec2-userとしてログイン)

[ec2-user@ip-555-432-111 ~]$ env | grep SECRET_KEY_BASE
SECRET_KEY_BASE='secret_key_base'

[ec2-user@ip-555-432-111 ~]$ env | grep DATABASE_PASSWORD
DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'

 

ポートの解放

立ち上げたばかりのEC2インスタンスは、HTTPなどの他の通信方法ではつながらないようになっている。

そのため、WEBサーバとして利用するEC2インスタンスが事前にHTTPがつながるよう、「ポート」を開放する設定を行う。

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

1.AWSのインスタンス画面から「セキュリティグループのリンク」をクリック

2.「インバウンド」タブの中の「編集」をクリック

3.モーダルが開くので、「ルールの追加」をクリック

タイプを「カスタムTCPルール」、プロトコルを「TCP」、ポート範囲を「3000」、送信元を「カスタム / 0.0.0.0」に設定する。

Railsを起動する

unicorn_rails というコマンドが使えるようになっているので、以下のコマンド(EC2サーバ)を実行する。

[ec2-user@ip-555-432-111 〜]$ cd /var/www/[リポジトリ]
[ec2-user@ip-555-432-111 <リポジトリ名>]$ unicorn_rails -c config/unicorn.rb -E production -D
MEMO
-c config/unicorn.rb は設定ファイルの指定、 -E production は環境を「本番モードとして動作させる」ことを示している。

しかし現状このコマンドを実行すると、以下のようにすぐにコマンドが終了してしまう。

[ec2-user@ip-555-432-111 [リポジトリ]]$ master failed to start, check stderr log for details

これはデータベースを作成していないことが起動しない原因となっているため、データベース作成の設定を行う。

データベース作成の前にアプリケーションのdatabase.ymlをローカル環境で編集する。

production:
  <<: *default
  database: ~~~(アプリケーション名によって異なる。こちらは編集しないこと)
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

ローカルでの編集をコミットして、GitHubにプッシュする。

リモートリポジトリが更新されたため、サーバ上のアプリケーションにも反映させる。

サーバのアプリケーションのあるディレクトリで以下のようにコマンドを実行する。

[ec2-user@ip-555-432-111 <リポジトリ名>]$ git pull origin master

続いてデータベースを作成しマイグレーションを実行し直す。

[ec2-user@ip-555-432-111 <リポジトリ名>]$ rails db:create 
Created database '<データベース名>'
[ec2-user@ip-555-432-111 <リポジトリ名>]$ rails db:migrate RAILS_ENV=production

データベースの準備が整ったので、再びRailsを起動する。

[ec2-user@ip-555-432-111 <リポジトリ名>]$ unicorn_rails -c config/unicorn.rb -E production -D

ブラウザで http://<サーバに紐付けたElastic IP>:3000/ にアクセスし、ブラウザに画面が表示されていれば成功

しかし現時点ではレイアウトが崩れているとので、アセットファイルのコンパイルを行う。

アセットファイルのコンパイル

アセットファイルとは?
画像・CSS・JSファイルの総称。本番モードではパフォーマンスのため、アクセス時に自動的にコンパイル(圧縮)する仕組みが実行されないようになっている

本番モードで事前にアセットをコンパイルするため、次のコマンドを実行する。

[ec2-user@ip-555-432-111 <リポジトリ名>]$ rails assets:precompile

コンパイルが成功したらRailsを再起動する。

まずは「ps」コマンドを打ち込み、現在動いているプロセスの確認を行う。今回はunicornのプロセスのみを抽出するため、下記コマンドを入力。

psコマンドとは?
現在動いているプロセスを確認するためのコマンド
[ec2-user@ip-555-432-111 <リポジトリ名>]$ ps aux | grep unicorn

下記のようにプロセスが表示(数字はバラバラ)されていれば成功

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

プロセスが確認できたら、「kill」コマンドを入力し現在動いているプロセスを停止させる。

killコマンドとは?
現在動いているプロセスを停止させるためのコマンド
[ec2-user@ip-555-432-111 <リポジトリ名>]$ kill -9 <確認したunicorn rails masterのPID>

これはローカルで行なっていたctrl + cでサーバをストップする作業と同じことをしたことになる。

Unicornを停止することができたら、再びunicornを起動させる。

このとき 「RAILS_SERVE_STATIC_FILES=1」 という指定を先頭に追加する。
こうすることで、コンパイルされたアセットをRailsが見つけられるような指定になる。

[ec2-user@ip-555-432-111 <リポジトリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
...

再度ブラウザで http://<Elastic IP>:3000/ にアクセスし、レイアウト崩れなくサイトが正常に表示されていれば成功。


次回(3)はここまでの流れを自動化するための「自動デプロイ」についてまとめたので、(2)が終わった方はお進み頂きたい。

AWSを用いたデプロイの流れ(3)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です