アプリの公開!

EC2のサーバにアプリのコードをクローン

・GithubにSSH鍵を登録
EC2サーバにアプリケーションのコードをクローンしようとしても、
エラーが出る。Githubから見てこのEC2インスタンスが何者かわからない。SSH鍵をGithubに登録すると、認証に利用しコードのクローンを許可する。

・EC2サーバのSSH鍵ペアを作成

ターミナル(EC2サーバ)

$ ssh-keygen -t rsa -b 4096
# 途中で passphrase など3段階ほど入力を求められることがあるが、何も入力せずにEnterキーで進む。

$ cat ~/.ssh/id_rsa.pub
# SSH公開鍵を表示。ssh-rsaで始まる長い公開鍵をコピー。

・catコマンド Linuxのコマンドの一つ。

①URLにアクセス →  https://github.com/settings/keys
②画面右上の緑 New SSH key をクリック。

画像1

③上記画面になれば Title 内を自由に記載する。
key 内にコピーしたssh-rsaで始まる公開鍵を貼り付ける。
⑤左下緑 Add SSH key をクリック。

$ ssh -T git@github.com
# SSH接続できるか確認。途中で続けるか聞かれることがあるが、Yesで進む。

Hi <Githubユーザー名>! You've successfully authenticated, but GitHub does not provide shell access.
# 上記メッセージが出れば成功。

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

・アプリケーションサーバ
Webサーバから受け取ったリクエストをもとに、Javaやphp、Rubyなどを
実行し、Webサーバに結果を返す。全世界に公開するEC2サーバ上も
アプリケーションサーバを動かす必要がある。
Ruby on Rails環境のアプリケーションサーバ
Unicorn、Thin、Rainbows、Pumaが有名。

・Webサーバ

Apache、nginx 、IIS(Internet Information Services)が有名。
楽天ではapache、Yahooではnginx、MicrosoftではIISが利用されている。

ユニコーン

良く利用されるアプリケーションサーバ。
rails sコマンドの代わりにunicorn_railsコマンドで起動。

・Unicornをインストール

Gemfile を編集

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

# このgroup :production do ~ endの間に記述されたgemは本番環境のみ読み込まれる。
# Unicornは本番環境で必要なので、ローカルでは不要。


ターミナル(ローカル)

$ bundle install
#自分でconfigディレクトリ以下に作成。
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

・worker(ワーカー)
Unicornはプロセスを分裂させる。分裂したプロセス全てをworkerと呼ぶ。プロセスを分裂させると、リクエストに対しレスポンスを高速にする。

・プロセス
PC(サーバ)上で動く全プログラムの実行時の単位。プログラムは、ブラウザや音楽再生ソフト、GUIや、Rubyなどのスクリプト言語の実行など。
プログラムが動いている数だけ、プロセスが存在する。
Macではアクティビモニタでプロセスを確認できる。
PID(プロセスアイディー) プロセスを識別する数字

・worker_processes
リクエストを受けレスポンスを生成するworker(ワーカー)の数を決める。

・working_directory
UnicornがRailsのコードを動かす際、ルーティングなど実際に参照する
ファイルを探すディレクトリを指定。

・pid

Unicornは、起動する際にプロセスidが書かれたファイルを生成。
その場所を指定。

・listen

どのポート番号のリクエストを受け付けることにするかを決定。
上記は3000番ポートを指定している。

デプロイ時にエラーの原因となる記述の対策

config/environments/production.rb を編集

# JavaScriptを軽量化するもの。JavaScriptで使用しているテンプレートリテラル記法に対応していないため、
# デプロイ時にエラーの原因となる。コメントアウトで対策する。
config.assets.js_compressor = :uglifier をコメントアウト


# 完了後 githubにpush & masterにmerge

Githubからコードをクローン

ターミナル(EC2サーバ)

# mkdirコマンドで新たにディレクトリを作成
$ sudo mkdir /var/www/

# 作成したwwwディレクトリの権限をec2-userに変更
$ sudo chown ec2-user /var/www/

Githubから「リポジトリURL」を取得。
ページ右側緑ボタン Clone or download をクリック後、URLをコピー。

ターミナル(EC2サーバ)

$ cd /var/www/

# http以降は先ほどコピーしたURL
$ git clone https://github.com/<ユーザー名>/<リポジトリ名>.git

本番環境での設定

・Swap(スワップ)領域
コンピュータが処理を行う際、メモリと呼ばれる場所に処理内容が一時的に記録される。メモリは容量が決まっており、容量を超えるとエラーで処理が止まる。Swap領域は、メモリの不足時に容量を一時的に増やすファイル。EC2はデフォルトでSwap領域を用意していないため、準備することでメモリ不足のエラーを防ぐ。

ターミナル(EC2サーバ)

$ cd

# 処理に時間がかかる可能性があるコマンド
$ sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512

# しばらく待って、以下のように表示されれば成功
512+0 レコード入力
512+0 レコード出力
536870912 バイト (537 MB) コピーされました、 7.35077 秒、 73.0 MB/秒

$ sudo chmod 600 /swapfile1
$ sudo mkswap /swapfile1
# 以下のように表示されれば成功
スワップ空間バージョン1を設定します、サイズ = 524284 KiB
ラベルはありません, UUID=74a961ba-7a33-4c18-b1cd-9779bcda8ab1


$ sudo swapon /swapfile1
$ sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab'

・クローンしたアプリケーションを起動するためにgemをインストール。

ターミナル(EC2サーバ)

# クローンしたディレクトリに移動し、 rbenvでインストールされたRubyが使われているかチェック
[ec2-user@ip-172-31-45-306 www]$ cd  /var/www/<リポジトリ名>

[ec2-user@ip-172-31-45-306 <リポジトリ名>]$ ruby -v
ruby 2.5.1p112 (2016-04-26 revision 54768) [x86_64-linux]
ターミナル(ローカル)

# 開発環境(ローカル)て、どのバージョンのbundlerが使われていたか確認。<リポジトリ名>のディレクトリで以下を実行
$ bundler -v

# 開発環境によってバージョンは異なります。
Bundler version 2.0.1
ターミナル(EC2サーバ)

# 同じバージョンのものをEC2サーバ側にも導入。
[ec2-user@ip-172-31-45-306 <リポジトリ名>]$ gem install bundler -v 2.0.1

# 上記コマンドは、数分以上かかる場合もある。
[ec2-user@ip-172-31-45-306 <リポジトリ名>]$ bundle install

環境変数の設定

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

・環境変数
Railsは ENV['<環境変数名>'] で利用できる。
config / secrets.yml  と  config / database.yml を確認。
<%= ENV ["SECRET_KEY_BASE"]%> は、
 SECRET_KEY_BASE という環境変数。

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

ターミナル(EC2サーバ)

# 実行後に表示される英数の羅列をコピー
[ec2-user@ip-172-31-45-306 <リポジトリ名>]$ rake secret

# EC2インスタンスに環境変数を設定。 /etc/environment に保存することで、サーバ全体に適用される
[ec2-user@ip-172-31-45-306 ~]$ sudo vim /etc/environment

vimコマンドについてはこちらの記事
画面が変更されたら i で挿入モードに切り替える。

/etc/environment を編集

# 下記を入力
DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'
SECRET_KEY_BASE='先程コピーしたsecret_key_base'

esc(エスケープキー)を押して、 :wq を入力して保存&終了。

ターミナル(EC2サーバ)

# 環境変数を適用するため,ログアウト
[ec2-user@ip-172-31-45-306 ~]$ exit

# EC2にログイン
$ ssh -i 〇〇.pem ec2-user@[作成したEC2インスタンスと紐付けたElastic IP]

# 環境変数が適用されているか確認。
[ec2-user@ip-172-31-45-306 ~]$ env | grep SECRET_KEY_BASE
SECRET_KEY_BASE='secret_key_base'

[ec2-user@ip-172-31-45-306 ~]$ env | grep DATABASE_PASSWORD
DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'

ポートの解放

EC2インスタンスはSSHでアクセスできるが、HTTP等、他の通信方法では
繋がりません。なのでWEBサーバとして事前にHTTPがつながるように
ポートを開放する必要があります。config/unicorn.rb に listen 3000 と
記述があります、これはRailsのサーバを3000番ポートで起動する意味。

・セキュリティグループのポートを設定
①EC2インスタンス一覧画面から、インスタンスを選択し、
セキュリティグループすぐ横のリンクをクリック。
②インバウンドルールをクリック。
③インバウンドのルールの編集をクリック。
④下記のように カスタムTCP を追加、保存。

ポート

本番環境でRailsを起動

ターミナル(EC2サーバ)

# ユニコーンを起動
[ec2-user@ip-172-31-45-306 ~]$ cd /var/www/[リポジトリ]

# 実行すると、以下のようにすぐにコマンドが終了する。
[ec2-user@ip-172-31-45-306 <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D
master failed to start, check stderr log for details

# エラーログの確認。mysqlへ接続できなくなっている状態。
[ec2-user@ip-172-31-45-306 <リポジトリ名>]$ less log/unicorn.stderr.log
ERROR -- : Can't connect to local MySQL server through socket '/tmp/mysql.sock'
config/database.yml を編集

production:
 <<: *default
 database: ~~~(ここは編集しない)
 username: root
 password: <%= ENV['DATABASE_PASSWORD'] %>
 socket: /var/lib/mysql/mysql.sock
ターミナル(EC2サーバ)

[ec2-user@ip-172-31-45-306 <リポジトリ名>] git pull origin master

# データベース作成
[ec2-user@ip-172-31-45-306 <リポジトリ名>]$ rails db:create RAILS_ENV=production
Created database '<データベース名>'

# マイグレーション実行
[ec2-user@ip-172-31-45-306 <リポジトリ名>]$ rails db:migrate RAILS_ENV=production

# 上記コマンドでエラーが出た場合。mysqlが起動していない可能性があるので下記を実行。
$ sudo service mysqld start

# Railsを再起動
[ec2-user@ip-172-31-45-306 <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -Dブラウザで http://<サーバに紐付けたElastic IP>:3000/ にアクセス

・ブラウザで  http: // <Elastic IP>:3000 / にアクセス。
ビューが崩れている画面が表示されればOK。

ターミナル(EC2サーバ)

# 事前にアセットをコンパイルする必要があるので実行。
[ec2-user@ip-172-31-45-306 <リポジトリ名>]$ rails assets:precompile RAILS_ENV=production

# unicornのプロセスを確認。 psコマンド は、プロセス確認コマンド。 aux psコマンドのオプション。
# | grep unicorn はunicorn関連のプロセスを抽出。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn

# 左から2番目がPID。unicorn_rails masterがプロセス本体。本体のPIDをコピー。
ec2-user 21515  0.4 15.1 588442 180840 ?       Sl   01:09   0:06 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 21529  0.0 13.3 589068 170164 ?       Sl   01:00   0:06 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 21622  0.0  0.2 110535  2185 pts/0    S+   08:05   0:00 grep --color=auto unicorn

# killコマンドはプロセスを停止させる。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <上記PID>

# 再度プロセス確認。下記成功例。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
ec2-user 21622  0.0  0.2 110535  2185 pts/0    S+   08:05   0:00 grep --color=auto unicorn

# 下記が残っていれば停止失敗
ec2-user 21515  0.4 15.1 588442 180840 ?       Sl   01:09   0:06 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 21529  0.0 13.3 589068 170164 ?       Sl   01:00   0:06 unicorn_rails worker[0] -c config/unicorn.rb -E production -D

# 下記で強制終了
$ kill -9 [PID]
ターミナル(EC2サーバ)

# unicorn再起動
[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/  アクセスでビューが崩れがなければOK。
通常のログの確認方法

ターミナル(EC2サーバ)

# 正常に動いているログも確認できる。 tailコマンド 指定したファイルの最後の行を表示する。
 -fオプションを追加すると、リアルタイムに更新される。 tail -fコマンドの終了は ctrl+c。 
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$tail -f log/production.log

次回は Nginx の導入

この記事が気に入ったらサポートをしてみませんか?