Help us understand the problem. What is going on with this article?

独学向けRailsアプリをAWSにデプロイする方法まとめ【入門】

EC2インスタンスの作成

AWSのサーバーであるEC2インスタンスの作成をしていきます。

AWSアカウントのリージョン設定をしよう

リージョンとは、AWSの物理的なサーバの場所を指定するものです。リージョンは世界各地に10箇所以上存在し、そのうちの一つは東京にあります。
リージョンを東京に設定していきましょう

手順

  1.  コンソールにアクセス 

  2. 画面右上にある『 国 』を『アジアパシフィック(東京)を選択』
    スクリーンショット 2020-01-10 13.48.30.png

EC2インスタンスを作成

「サーバーを生成する」といっても、AWSが全てのサーバを物理的に用意しているわけではなく、実際には「仮想マシン」と呼ばれるソフトウェアを利用しています。
この「仮想マシン」のことをAWSでは「EC2インスタンス」と呼んでいます。

手順

  1. AWSにアクセス

  2. EC2を選択する
    Image from Gyazo

  3. 画面右上にある、『New EC2 Experience』をオン
    ※アンケートは『 キャンセル 』 しましょう。
    Image from Gyazo

  4. 『実行中のインスタンス』をクリック
    スクリーンショット 2020-01-10 14.14.20.png

  5. インスタンスの画面が開かれたら、画面左上の 『インスタンスの作成』 をクリック
    スクリーンショット 2020-01-10 14.17.36.png

  6. 「 Amazon Linux2 AMI 」ではなく、「 Amazon Linux AMI 」を選択してください。
    (上から2番目にあります)
    Image from Gyazo

  7. 無料枠で利用できる「t2.micro」を選択し、画面右下の 『確認と作成』 をクリック
    スクリーンショット 2020-01-10 14.25.06.png
    ( EC2インスタンスのタイプを選択します。EC2ではさまざまなインスタンスタイプが用意されており、CPUやメモリなどのスペックを柔軟に指定することができます。)

  8. 画面右下の『起動』をクリック
    スクリーンショット 2020-01-10 14.28.11.png

  9. 『新しいキーペアの作成』を選択
    Image from Gyazo

  10. キーペア名を入力(空白NG)

  11. キーペアのダウンロード(ファイル名.pem)

スクリーンショット 2020-01-10 14.36.47.png
🚨注意:こちらはインスタンスにSSHでログインする際に必要となる「秘密鍵」です。これがないとEC2インスタンスにログインできないので、必ずダウンロードしてパソコンに保存しておきましょう。また、間違って他人に渡さないよう気をつけてください。
ダウンロードしたpemキー(ファイル名.pem)のsshフォルダに移行する

$ cd ~ 
#ターミナルをスタート地点に戻す

$ mkdir ~/.ssh  
#.sshというディレクトリを作成
# エラー『 mkdir: /Users/owner/.ssh: File exists 』と表示の場合、すでに存在します


$ mv Downloads/ファイル名.pem .ssh/
# mvコマンドで、移動させたい対象(ファイル名.pem) → .sshディレクトリに移動します。

$ cd .ssh/

$ ls
# pemファイルが存在するか確認します

12.画面右下の『インスタンスの作成』をクリック
13. 作成完了(反映に時間がかかる場合があります)
スクリーンショット 2020-01-10 14.39.41.png
14.次のインスタンスの作成がされました: 『 i- 』のインスタンスIDをクリック

スクリーンショット 2020-01-10 14.44.47.png
15. 作成したインスタンスがrunningと表示されて、稼働している
スクリーンショット 2020-01-10 14.47.05.png

完了

次は『 Elastic IPの作成と紐付け 』をしよう

先ほど作成したEC2インスタンスには、作成時にIPアドレスが自動で割り振られています。これをパブリックIPと言います。しかし、サーバーを再起動させるたびにこのパブリックIPが変わってしまうという欠点を持っています。

次回はその欠点を改善するために、『 Elastic IPの作成と紐付け 』をしていきましょう。

EC2インスタンスをElastic IPで固定

作成したEC2インスタンスには、作成時にIPアドレスが""自動""で割り振られています。
これをパブリックIP(一般公開用のID)と言います。
しかし、""サーバーを再起動させるたびにこのパブリックIPが変わってしまうという欠点""を持っています。

そのため、パブリックIDを固定して、いちいち更新しないようにします。
この固定化したパブリックIDを『 Elastic IP 』と呼びます。

今回はその欠点を改善するために、『 EC2インスンタンスとElastic IP紐付け 』をしていきましょう。

Elastic IPの作成

EC2インスタンスのパブリックIPアドレスをElastic IPに固定する。
Elastic IPとは、AWSから割り振られた固定したパブリックIPアドレス。
このパブリックIPアドレスをEC2インスタンスに紐付けることで、インスタンスの起動、停止に関わらず常に同じIPアドレスで通信をすることが可能になります

手順

  1. AWSのサイドナビにある、『Elastic IP』をクリック。こちらからでも進めます
    Image from Gyazo

  2. 『 Elastic IP アドレスの割り当て 』をクリック
    スクリーンショット 2020-01-10 15.14.40.png

  3. 画面右下の『 割り当て 』をクリック
    スクリーンショット 2020-01-10 15.13.53.png

  4. Elastic IPの作成完了(緑の帯に作成されたElastic IPアドレスが記載されています。)
    スクリーンショット 2020-01-10 15.18.09.png

Elastic IPアドレスは、パブリック IPv4 アドレスの項目にも記載されています(公開するわけにはいかないので伏せています)
スクリーンショット 2020-01-10 15.22.59.png

Elastic IPアドレスとEC2インスタンスと紐付け

ここからEC2インスタンスとElastic IPアドレスを紐付けします。
紐付けが完了すれば、EC2インスタンスのパブリックIPは、Elastic IPアドレスで固定されます

手順

  1. Elastic IPアドレスを選択✅
  2. アクション 『Elastic IPアドレスの関連付け』をクリック
    スクリーンショット 2020-01-10 15.29.25.png

  3. 作成したEC2インスタンスを選択
    スクリーンショット 2020-01-10 15.33.22.png
    補足:上の画像のようにインスタンスを選択すると、その下にあるプライベートIPアドレスが自動で選択されます。なのでプライベートIPアドレスは空白で大丈夫です

4.画面右下の『関連付ける』をクリック
スクリーンショット 2020-01-10 15.35.50.png

5.紐付け完了
スクリーンショット 2020-01-10 15.38.46.png

無事に関連づけられたインスタンスに『i- (EC2インスタンスID)』が表示されています

次は AWS セキュリティグループの設定

立ち上げたばかりのEC2インスタンスはSSHでアクセスすることはできますが、HTTPなどの他の接続は一切つながらないようになっています。そのため、WEBサーバとして利用するEC2インスタンスは事前にHTTPがつながるように「ポート」を開放する必要があります

次回はポート解放の操作をお伝えしていきたいと思います。

AWSセキュリティグループの設定

前回までの流れ

作成したEC2インスタンスとElastic IPを紐付けして、パブリックIPを固定にした。

今回の流れ

現状

現時点において、HTTP(www.サイトURL)で接続することはできない。
スクリーンショット 2020-01-10 16.13.43.png
(ターミナルでEC2とSSH接続は可能。)

つまり、一般ユーザーは閲覧することはできない状態である。
なので、今回はHTTP接続(www.)を解放して、URLでサイトを閲覧できるようにしていく。

現実で比喩

従業員は店舗に入れるけど、お店は開店させていないので、お客さんは入店できない。
>入り口を解放する必要がある

ポート(入り口)の解放

このHTTP接続(www.)の入り口となるのが、「ポート」(扉)と呼ばれます。IPアドレスが住所「家」であれば、ポートは外に出る・外から入る「扉(ドア)」に該当します。

ポートの設定をするためには、「セキュリティグループ」という設定を変更していきましょう

本題、セキュリティグループの設定

セキュリティグループとは、AWSのファイアウォール機能の一つ。
プロトコル、ポート範囲、送信元/送信先IPアドレスによるパケットフィルターが可能。
インスタンス単位に適用することができる。

手順

  1. AWSのEC2ダッシュボードを開く Image from Gyazo
  2. 『実行中のインスタンス』をクリック Image from Gyazo
  3. インスタンスを選択
    スクリーンショット 2020-01-10 16.34.14.png

  4. セキュリティグループの『launch-wizard-3』をクリック

スクリーンショット 2020-01-10 16.37.48.png

補足: インバウンドルール(この後追加します)
そのセキュリティグループに関連付けられたインスタンスにアクセスできるトラフィックを規制する。『インバウンドルールの表示』をクリックすると下記が表示される。
スクリーンショット 2020-01-10 16.36.31.png

補足: アウトバウンドルール(この後追加します)
そのセキュリティグループに関連付けられたインスタンスからどの送信先にトラフィックを送信できるか(トラフィックの送信先と送信先ポート)を制御するルール
『アウトバウンドルールの表示』をクリックすると下記が表示される。
スクリーンショット 2020-01-10 16.36.49.png

(ここから、セキュリティグループの『launch-wizard-3』をクリック後に続く)
5. 下記の画面が表示される
68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3435353430332f37323334663664362d323935342d626334662d643634662d3466633236353061303066312e706e67 (1).png

6.『 インバウンド 』を選択
スクリーンショット 2020-01-10 20.49.20.png
7. 『 編集 』をクリック
スクリーンショット 2020-01-10 20.57.06.png
8. 左下の『ルールの追加』をクリック
Image from Gyazo
9. タイプ:『 HTTP 』を選択
スクリーンショット 2020-01-10 21.03.27.png
10. 画面左下の『 保存 』をクリック
スクリーンショット 2020-01-10 21.08.22.png

スクリーンショット 2020-01-10 21.07.29.png
11. 完了
これでIPアドレス、WWW.やドメインでのWEB閲覧が可能となります。

次はEC2にSSHログインしていきましょう!

ここまで、お疲れ様でした。
なかなか慣れない作業で疲れたのではないでしょうか?

セキュリティグループについては、下記記載のAWSのセキュリティグループリファレンスを参照してみるといいかもしれません。

次回は自身で作成したWEBアプリとEC2サーバーを紐づけていくために、SSHログインしましょう

次回の記事はこちら!
はじめてAWSでデプロイする方法④(EC2にSSHログイン)

参考

【AWS】セキュリティグループを設定してみた
AWS公式-セキュリティグループのルールのリファレンス

EC2インスンタンスにSSHログイン

EC2インスタンス(サーバー)を作成し、パブリックIPをElastic IPで固定。
一般ユーザーがアクセスできるように、セキュリティグループの設定を追加(入り口を作成)
ざっくり説明すると、こんなところです。

今回実施すること

今回はEC2上にRailsやMySQLなどをインストールする、つまり環境構築をするために、SSH接続でEC2にログインをしていきます。
EC2にログインするにはどうすればいいのか?

IDとPWが必要です。
ID = Elastic IP(パブリックIP)
PW = pemキー(EC2インスタンス作成時にダウンロードしたファイル)

上記2点を利用して、ログインしていきますが、その方法を解説していきます

EC2インスタンスにログインする

ここからは、実際にログインする説明をしていきます。

始める前の前提条件

EC2インスタンスを作成すると、ec2-userというユーザーと対応するSSH秘密鍵が生成されます。
このアカウントは管理者権限が強いので、本来であればこのec2-userではなく、権限を小さいアカウント使って運用します。

まずは基本を掴むために、このec2-userを使って作業を進めていきます。

保存しておいた(ファイル名.pem)のアクセス権限の制限

SSH接続でログインをするために、暗号化キーである,ファイル名.pemを保護したいと思います。

pemキー(ファイル名.pem)は,
はじめてAWSでデプロイする方法①(インスタンスの作成)でインスタンス作成時にダウンロードしたファイルです

このファイルに秘密鍵が記載されるので、不正利用されないように、アクセス制限をかけます。
このファイルは、、他者に閲覧されないように制限をかけることが目的です。このファイルやディレクトリのアクセス権の設定することをパーミッション(許諾)と呼びます。

パーミッション(ファイルのアクセス制限)をするには、 $ chmod コマンドを利用します。 

手順

$ cd ~/.ssh

$ ls
# pemファイルが存在するか確認しましょう
# ない場合は、『はじめてAWSでデプロイする方法①(インスタンスの作成)』を振り返ってください

$ chmod 600 ダウンロードした鍵の名前.pem

この$ chmod 600の解説をしたいと思います。

まず、chmodはアクセス制限をかけるパーミッションを設定するためのコマンドとお伝えしました。600は『 誰に 』どんな権限を与えるのか設定しています。

誰に?は下記になります。

  • 100桁は『所有者の権限設定』
  • 10桁は『グループの権限設定』
  • 1桁は『その他のユーザーの権限設定』
$ chmod 600の場合
6 = 『所有者の権限設定』
0 = 『グループの権限設定』
0 = 『その他のユーザーの権限設定』

『 どんな権限を与えるのか? 』は下記になります

0 1 2 3 4 5 6 7
--- --x -w- -wx r-- r-x rw- rwx

r = read = 読む(閲覧)権限
w = write = 書く(入力、編集)権限
x = 実行する権限

6 はrw 読み書きの権限を与えます。
0は一切の権限がありません。

$ chmod 600の場合
 『所有者の権限設定』 = 6 = rw- = 読み書き
 『グループの権限設定』 = 0 = --- = 権限なし
 『その他のユーザーの権限設定』 = 0 = --- = 権限なし

もう一度見てみましょう

$chmod 600 webapp.pem 

webapp.pemは、
『所有者権限』 6 = rw = 読み書きが可能
『グループ権限』 0 = 権限なし
『他ユーザの権限』 0 = 権限なし

#注意:この操作をしていないと、sshでログインができません。
(xの実行を入れていないのは、ファイル名.pemが何かのプログラムを実行するファイルではないため。700でも可能)

詳細については、下記の記事を参考にしてください
Macターミナルコマンド「chmod」の使い方
参考:chmod コマンド

ファイル名.pemに制限をかけたところで、安心してログインしていきましょう!

SSH接続による、ログイン

pemキーの制限をかけたところで、ログインを実際にしていきます。

$ cd ~/.ssh
# .sshディレクトリに移行
.ssh $ ls
# .sshディレクトリに無事にpemキーが入っているのか確認

.ssh $ ssh -i ファイル名.pem ec2-user@Elastic IP(EC2インスタンスと紐付けた)
#例
 # 条件: 『 pemキー = webapp.pem 』、 『 Elastic IP = 123.456.789 』 であれば
 # 実行コマンド: ssh -i webapp.pem ec2-user@123.456.789
 # pemキーはlsコマンドで、ファイルの一覧が表示されるので、そこからコピーしましょう

Elastic IPの確認

  1. EC2を開く
  2. 実行中のインスタスを開く

スクリーンショット 2020-01-11 19.29.54.png
3. 下記写真の右下に、『 Elastic IP: 』と記載されているのでコピー
スクリーンショット 2020-01-11 19.21.03.png

無事にログインが成功されるとEC2の表示が出る
スクリーンショット 2020-01-11 19.40.24.png

これでログイン完了です👍
お疲れ様でした!!!

エラーが出る場合は、下記を確認ください。

エラーが表示された場合

エラー「-bash: shh: command not found」が表示された場合

スクリーンショット 2020-01-11 19.16.06.png

答え1:Elastic IPの「*」は不要
スクリーンショット 2020-01-11 19.19.05.png

Elastic IPの「●●.●●●.●●●.●●●*」の最後のアスタリスクは不要
下記写真の右下に、『 Elastic IP: 』と記載されているので、ここでコピーしましょう!
スクリーンショット 2020-01-11 19.21.03.png

エラー「WARNING: UNPROTECTED PRIVATE KEY FILE!」 の場合

スクリーンショット 2020-01-11 19.34.41.png

答え2: pemキーがchmodでパーミッションされていません。
>操作手順を上に戻って、chmodコマンドでパーミッションを実施してください。

エラー「Warning: Identity file : No such file or directory.Permission denied (publickey).」

下記は重要な箇所は虫食い状態にしています。
スクリーンショット 2020-01-11 19.45.49.png

答え: sshコマンドを実施する場所が間違っている
>sshディレクトリ上で実施する必要があるが、sshディレクトリをターミナルで開いていない。

$cd ~/.ssh
.ssh $ ssh -i ファイル名.pem ec2-user@Elastic IP(EC2インスタンスと紐付けた)
#例
 # 条件: 『 pemキー = webapp.pem 』、 『 Elastic IP = 123.456.789 』 であれば
 # 実行コマンド: $ shh -i webapp.pem ec2-user@123.456.789
 # pemキーはlsコマンドで、ファイルの一覧が表示されるので、そこからコピーしましょう

次回はログイン後の環境構築を実施していきましょう!

ここまで、お疲れ様でした
ログインできた達成感を味わっていただけましたか?

次回は、EC2にログイン後の操作(環境構築)をしていきたいと思います

EC2の環境構築(Ruby, MySQL, etc)

EC2インスタンス(サーバー)を作成し、パブリックIPをElastic IPで固定。
一般ユーザーがアクセスできるように、セキュリティグループの設定を追加(入り口を作成)
IDとPWを使って、EC2にログイン

ざっくり説明すると、こんなところです。

今回の内容

ssh接続でログインをして、環境構築をする。

[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y update
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install git make gcc-c++ patch libyaml-devel libffi-devel libicu-devel zlib-devel readline-devel libxml2-devel libxslt-devel ImageMagick ImageMagick-devel openssl-devel

Node.jsをインストール

[ec2-user@ip-172-31-25-189 ~]$ sudo curl -sL https://rpm.nodesource.com/setup_6.x | sudo bash -

※追記:下記の表示が出ますが、setup_6.xのサポートが終了したので、別のバージョンを推奨する表示となります。
Image from Gyazo

[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install nodejs

rbenvとruby-buildをインストール

[ec2-user@ip-172-31-25-189 ~]$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
[ec2-user@ip-172-31-25-189 ~]$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
[ec2-user@ip-172-31-25-189 ~]$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
[ec2-user@ip-172-31-25-189 ~]$ source .bash_profile

上記をしないと エラー『 -bash: rbenv: コマンドが見つかりません 』が表示

[ec2-user@ip-172-31-25-189 ~]$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
[ec2-user@ip-172-31-25-189 ~]$ rbenv rehash

Rubyをインストール

[ec2-user@ip-172-31-25-189 ~]$ rbenv install 2.5.1

ここでエラースクリーンショット 2020-01-11 20.57.41.png
「-bash: rbenv: コマンドが見つかりません」が表示された場合、

rbenvとruby-buildをインストールを見直してください。

スクリーンショット 2020-01-11 20.55.27.png
インストールには時間がかかります。
このまま待ちましょう

[ec2-user@ip-172-31-25-189 ~]$ rbenv global 2.5.1
[ec2-user@ip-172-31-25-189 ~]$ rbenv rehash
[ec2-user@ip-172-31-25-189 ~]$ ruby -v

バージョンが表示されれば、
スクリーンショット 2020-01-11 21.00.04.png

無事にインストールされています

MySQLをインストール

[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install mysql56-server mysql56-devel mysql56

(mysql56は、MySQLのバージョン5.6をインストールすることを意味)

MySQLを起動

[ec2-user@ip-172-31-25-189 ~]$ sudo service mysqld start

MySQLの起動確認

[ec2-user@ip-172-31-25-189 ~]$ sudo service mysqld status

スクリーンショット 2020-01-11 21.07.34.png
runningが表示されていれば、稼働しています。

MySQLのrootパスワードの設定

この操作はPW設定をします
>PWを入力してから、コマンドを実行してください

[ec2-user@ip-172-31-25-189 ~]$ sudo /usr/libexec/mysql56/mysqladmin -u root password 'PWを入力'

下記の表示が出てきます。
Image from Gyazo

Warning: Using a password on the command line interface can be insecure.

翻訳「警告:コマンドラインインターフェイスでパスワードを使用することは安全ではありません。」
これに関しては下記の資料をご確認ください
資料1
資料2

ここでエラーが表示された場合
EC2 MySQL 初期設定 root にパスワードの設定

MySQLに接続(ターミナルでコマンド操作可能)

[ec2-user@ip-172-31-25-189 ~]$ mysql -u root -p

ここでPWが要求されます。
>登録したPWを入力してみて、無事に開かれるか確認しましょう!

下記が表示されたら、成功です
スクリーンショット 2020-01-11 21.43.51.png

PWが正しく登録できたことを確認できたので、

$ exit

でMySQLの接続を解除しましょう

EC2インスタンスにAppをクローンしてアップロード

EC2インスタンス(サーバー)を作成し、パブリックIPをElastic IPで固定。
一般ユーザーがアクセスできるように、セキュリティグループの設定を追加(入り口を作成)
IDとPWを使って、EC2にログインして、環境構築をしました。

ざっくり説明すると、こんなところです。

今回はWEB AppをEC2インスタンスにアップロードしていきます。

WEB AppをEC2にクローンする

現段階

EC2サーバにアプリケーションのコードをクローンしようとしてもpermission deniedとエラーが出てしまいます。

原因

Githubから見てこの許可していないEC2インスタンスを拒否する

対策

EC2インスタンスのSSH公開鍵をGithubに登録する。

SSH鍵をGithubに登録すると、Githubはそれを認証してクローンを許可をだす

作業

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

  1. EC2にログイン
  2. キーペア作成のためコマンドを入力
[ec2-user@ip-172-31-23-189 ~]$ ssh-keygen -t rsa -b 4096

3.下記が表示されるので、エンターを押す

Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa):

4.さらにエンターを押す(2回)

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              |
+-----------------+

5.SSH公開鍵を表示し、値をコピーするため、下記コマンドを実装

[ec2-user@ip-172-31-23-189 ~]$ cat ~/.ssh/id_rsa.pub

6.catで表示させた公開鍵(長いテキスト)をコピー
スクリーンショット 2020-01-12 11.44.25.png

コピーした公開鍵をGithubにアクセスして登録する

  1. https://github.com/settings/keysにアクセス

スクリーンショット 2020-01-12 11.54.04.png
2. 画面右上の緑色の『 NEW SSH KEY 』をクリック
Image from Gyazo
3. タイトルを記入する(なんでも可能)
スクリーンショット 2020-01-12 12.00.39.png
4. 公開鍵(ssh-rsaから)を貼り付け
スクリーンショット 2020-01-12 12.00.56.png
エラー「Key is invalid. You must supply a key in OpenSSH public key format」が表示された場合、
貼り付けたコードに『 ssh-rsa 』が含まれているかご確認ください
スクリーンショット 2020-01-12 12.00.08.png
5. 『 Add SSH KEY 』をクリックして保存。
6. GithubのPWを入力
スクリーンショット 2020-01-12 11.59.26.png
7. 完了
スクリーンショット 2020-01-12 11.52.46.png
8. 登録できているか確認

[ec2-user@ip-172-31-23-189 ~]$ ssh -T git@github.com

下記の表示が出た場合: 『 yes 』を選択

The authenticity of host 'github.com (IP ADDRESS)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)?

この際に

Warning: Permanently added the RSA host key for IP address '52.111.11.11' to the list of known hosts.

と表示された場合は, EC2に入り直しましょう。更新されたのでエラーなく入れます。
成功すると、下記の表示になるはずです。

または、下記が表示された場合: 『 yes 』を選択

The authenticity of host 'github.com (IP ADDRESS)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)?

成功すると下記の表示が出る

[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.

参考:GitHub公式

App側でUnicornのインストール

EC2にGit クローンする前に、準備としてUnicornをインストールさせましょう
Gemfileにgem'unicorn'を追加

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

bundle installでインストール

$ bundle install

config/unicorn.rbを作成
スクリーンショット 2020-01-12 19.02.45.png
追加したunicorn.rbに下記を記述

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

production.rbを開き、下記の記述をコメントアウトする

config/environments/production.rb
config.assets.js_compressor = :uglifier
config/environments/production.rb
#config.assets.js_compressor = :uglifier

アプリケーションの保存先となるディレクトリを作成

ディレクトリの作成

#/var/wwwディレクトリを作成(後述するCapistranoの初期値がwwwなので、ディレクトリをwwwに設定しています)
[ec2-user@ip-172-31-23-189 ~]$ sudo mkdir /var/www/

作成したディレクトリをchownコマンドで権限設定

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

作成したディレクトリに移行

[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/

git clone でAppをEC2にダウンロード

GithubからGit cloneするためのリポジトリURLを取得
スクリーンショット 2020-01-12 21.42.36.png

git clone で作成したディレクトリにappをクローン

[ec2-user@ip-172-31-23-189 www]$ git clone リポジトリURL

Githubのアカウント名とPWを入力し、
ダウロードが開始される

remote: Enumerating objects: 298, done.
remote: Counting objects: 100% (298/298), done.
remote: Compressing objects: 100% (190/190), done.
remote: Total 298 (delta 109), reused 274 (delta 86), pack-reused 0
Receiving objects: 100% (298/298), 58.53 KiB | 365.00 KiB/s, done.
Resolving deltas: 100% (109/109), done.

完了

これで、EC2にAppがクローンされています。

EC2にgemをインストール

EC2のメモリを増強する

Swap(スワップ)領域を設定

Swapは、EC2のメモリが限界に達したとき、補う形でメモリの容量を増やす機能です。
デフォルトではSwap領域が設定されていないので、設定しましょう

手順

ホームディレクトリに移行

[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

うまくいくと、下記の表示が出ます

512+0 レコード入力
512+0 レコード出力
536870912 バイト (537 MB) コピーされました、 5.19011 秒、 103 MB/秒

次は権限に制限をかけましょう(chmodコマンド)

[ec2-user@ip-172-31-25-189 ~]$ sudo chmod 600 /swapfile1

スワップ(swap)領域を作成する - mkswap

[ec2-user@ip-172-31-25-189 ~]$ sudo mkswap /swapfile1

#成功すると下記の表示が出ます
スワップ空間バージョン1を設定します、サイズ = 524284 KiB
ラベルはありません, UUID=74a961ba-7a33-4c18-b1cd-9779bcda8ab1

スワップ(swap)領域を有効化する - swapon

[ec2-user@ip-172-31-25-189 ~]$ sudo swapon /swapfile1

エラーが出なければ成功です。
エラー「swapon: /swapfile1: スワップヘッダの読み込みに失敗しました: 無効な引数です」が表示された場合は、一つ前の手順に戻ってmkswapコマンドを実施してください。

下記のコマンドを実施してください。
🚨長いので、気をつけてください

[ec2-user@ip-172-31-25-189 ~]$ sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab' 

これで完了

参考になる記事:linux スワップ(swap)領域の作成

gemのインストール

まずは、EC2にダウンロードしたWEB Appを開く

[ec2-user@ip-172-31-23-189 www]$ cd  /var/www(作成したディレクトリ)/アプリ名

Rubyのバージョンを確認する

[ec2-user@ip-172-31-23-189 <アプリ名>]$ ruby -v

指定したrubyのバージョンが表示されれば成功です。

ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]

ローカル上のターミナルでbundlerのバージョンを確認する

EC2ではなく、ローカル環境のWEB Appを開き、下記コマンドを実施

$ bundler -v

するとバージョンが表示されます

Bundler version 2.0.2

これと同じバージョンをEC2で入れます。
🚨下記のバージョンをそのまま (2.0.1)を入れるとエラーが発生するので注意

[ec2-user@ip-172-31-23-189 <アプリ名>]$ gem install bundler -v 2.0.1

EC2でbundle installをして、gemをインストール

[ec2-user@ip-172-31-23-189 <アプリ名>]$ bundle install

エラーがなければ、gemのインストール完了です。

エラーが発生した場合

下記のエラーが表示された場合、インストールするべき bundler -vが間違っています

Traceback (most recent call last):
    2: from /home/ec2-user/.rbenv/versions/2.5.1/bin/bundle:23:in `<main>'
    1: from /home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/2.5.0/rubygems.rb:308:in `activate_bin_path'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/2.5.0/rubygems.rb:289:in `find_spec_for_exe': can't find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException)

エラーがある場合は、アプリ側の bundlerのバージョンを確認してください

$ bundler -v
>Bundler version 2.0.2

[ec2-user@ip-172-31-23-189 <アプリ名>]$ bundler -v
>Bundler version 2.0.1
>バージョンが違うので、エラーがおきます

インストール完了後、下記の表示があった場合

Post-install message from chromedriver-helper:

  +--------------------------------------------------------------------+
  |                                                                    |
  |  NOTICE: chromedriver-helper is deprecated after 2019-03-31.       |
  |                                                                    |
  |  Please update to use the 'webdrivers' gem instead.                |
  |  See https://github.com/flavorjones/chromedriver-helper/issues/83  |
  |                                                                    |
  +--------------------------------------------------------------------+

gem'chromedriver-helper'のサポートが終了しているので、代わりとなるgem 'webdrivers'をインストールすることを推奨しているメッセージとなります。

 group :test do
   # ...
-  gem 'chromedriver-helper'
+  gem 'webdrivers'

参考記事

環境変数の設定

前回までの流れ

EC2インスタンスを作成
Elastic IP でEC2インスタンスのパブリックIPを固定
セキュリティグループを編集して、HTTPでWEBサイトの入り口を作る。
EC2にRails等をインストールして、環境設定をする
いよいよAppをEC2にダウンロード(クローン)
gemをインストール

今回の内容

環境変数を設定する。

環境変数とは何か?

環境変数は簡単に説明すると、PWを公開しないための変数と思ってください。

Githubは開発するに際に非常に便利です
コードのバックアップのような役割も担うし、他の開発チームとコードを共有することができる。

しかし、PWは公開したくないはずです。
このPW(パスワード)などの公開したくない情報を環境変数というもので隠してしまいます。

変数はX=3のように 文字(X)の意味(3)を定義します。
環境変数の場合、環境変数 = 'PW' のように、パスワードを変数の値とします。
こうすることで、コードに記述されている環境変数だけでは、パスワードを特定できないので、
悪用されない仕組みとなります。

環境変数で定義したPWは、開発者のみが’鍵(暗号化を解除するための数値)’を持っており、鍵を持っている人間しか、実際の値をみることができません。

secret_key_baseの取得

secret_key_baseは「railsアプリ」でクッキーを暗号化するものになります。
クッキーとは、webを参照した時の履歴のようなものを残し、次回から素早くアクセスできるものになります。
クッキーは外部から参照されるとよくないので暗号化します。

[ec2-user@ip-172-31-23-189 <アプリ名>]$ rake secret

# うまくいくと、
cdfasdfadgfsadfdgc314751a8dadfadf7c8b9a1dc888e...
という感じで表示されます。
これをコピーしておきましょう

環境変数を設定

環境変数を記述する場所を開きましょう

[ec2-user@ip-172-31-23-189 <アプリ名>]$ sudo vim /etc/environment

すると下記のような画面が表示されます。
スクリーンショット 2020-01-14 18.32.12.png

編集をするために「i」を入力
スクリーンショット 2020-01-14 18.35.52.png

すると 『 -- 挿入 -- 』と表示されるので、入力が可能となります。
では、環境変数を定義していきましょう

DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'
SECRET_KEY_BASE='先程コピーしたsecret_key_base'

入力が完了したら、キーボード左上にある『 esc 』を押します。
すると挿入の表示が消えます。
保存するために 『 :wq 』 と入力しましょう

すると見慣れたターミナルの画面に戻ります
スクリーンショット 2020-01-14 18.42.42.png

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

[ec2-user@ip-172-31-23-189 ~]$ exit

もう一度EC2にログイン
(ターミナル上で↑を押すと、入力してきたコマンドが出てくるので、それでssh -iを見つけてエンターすれば大丈夫です)

$ ssh -i ファイル名.pem ec2-user@[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='MySQLのrootユーザーのパスワード'

これで以上です。

何かAPIを導入したい際は、APIの秘密鍵を同じようにして環境変数として設定します。

Railsの起動

ポートの解放

config/unicorn.rb に listen 3000 と記述しましたが、これはRailsのサーバを3000番ポートで起動するということを意味するのでした。
HTTPがつながるように「ポート」を開放する必要があります。

手順

1.EC2を開く
スクリーンショット 2020-01-14 19.47.31.png
2. 『実行中のインスタンス』を開く
3. インスタンスを選択
スクリーンショット 2020-01-10 16.34.14.png
4. セキュリティグループの『launch-wizard-3』をクリック
スクリーンショット 2020-01-10 16.37.48.png
5. 下記の画面が表示される
68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3435353430332f37323334663664362d323935342d626334662d643634662d3466633236353061303066312e706e67 (1).png
6.『 インバウンド 』を選択
スクリーンショット 2020-01-10 20.49.20.png
7. 『 編集 』をクリック
スクリーンショット 2020-01-10 20.57.06.png
8. 左下の『ルールの追加』をクリック
Image from Gyazo
9. タイプ:「カスタムTCPルール」、プロトコルを「TCP」、ポート範囲を「3000」、送信元を「カスタム」「0.0.0.0/0」に設定
スクリーンショット 2020-01-14 19.56.35.png
10. 画面左下の『 保存 』をクリック

Railsの起動

Rails 5.1以前の場合

database.ymlに下記を追加します

config/database.yml(ローカル)
production:
  <<: *default
  database: アプリ名
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

追記が完了したら、EC2でも反映させます。
EC2とGithubは接続できているため、git pullコマンドを利用します。

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <アプリ名>] git pull origin master

データベースの作成をする

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <アプリ名>]$ rails db:create RAILS_ENV=production
Created database '<データベース名>'

この際に下記の表示が出た場合、、、うまくいっていません。
スクリーンショット 2020-01-18 22.03.37.png

アプリのディレクトリを開いてからコマンドを実行しましょう

#うまくいかない = アプリ名を指定していない
[ec2-user@ip-172-31-23-189 ~( ここが指定されていない )]$ rails db:create RAILS_ENV=production
Created database '<データベース名>'

#アプリ名(リポジトリ)を指定しているのでちゃんと処理がされる
[ec2-user@ip-172-31-23-189 <アプリ名>]$ rails db:create RAILS_ENV=production
Created database '<データベース名>'


rails db:migrateを実行して、migrationを完了させる。

ターミナル(EC2)
[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'というエラーが起こった場合、mysqlが起動していない可能性があります。

ターミナル(EC2)
sudo service mysqld start

#再起動をさせたい場合は、
sudo service mysqld restart

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

参考記事
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

ユニコーンを起動

[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/[リポジトリ]
[ec2-user@ip-172-31-23-189 <app名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D

Rails5.2以降の場合

credentials.ymlの設定

ターミナル(ローカル)
アプリ名 $ EDITOR=vim bin/rails credentials:edit

すると編集画面が表示されます。
しかし文字入力ができないので、
『 i 』を押して、----INSERT----モードに変更します

下記を入力します。

credentials.yml
db:
  database: アプリ名
  username: root
  password: 設定したPW
  socket: /var/lib/mysql/mysql.sock

passwordははじめてAWSでデプロイする方法⑤(EC2の環境構築、Ruby, MySQL)の『MySQLのrootパスワードの設定』で設定しています。

次に、database.ymlにcredential.ymlで設定した環境変数を記述します

config/database.yml
production:
  <<: *default
  database: <%= Rails.application.credentials.db[:database] %>
  username: <%= Rails.application.credentials.db[:username] %>
  password: <%= Rails.application.credentials.db[:password] %>
  socket: <%= Rails.application.credentials.db[:socket] %>

本番環境のshared/configにmaster.keyを作成

手順

ローカル環境にある,master.keyの中身を確認する

rails newで作成された、ローカルのmaster.keyを確認する。

$ vi config/master.key

すると下記のようにmaster.keyの中身が表示されます。

fadfdfdgaf44623535y....

この表示された、master.keyの値をコピーしましょう

スクリーンショット 2020-01-18 18.20.47.png
表示されたmaster.keyをコピーします。
これを本番環境で貼り付けていきます。

本番環境でmaster.keyを作成

EC2のアプリのconfigを開きましょう

#本番環境
[ec2-user@ip-172-31-23-189 ~]$ cd /var/ここはそれぞれ違います/[アプリ名]
[ec2-user@ip-172-31-23-189 <アプリ名>]$ cd shared/config

そうしたら、本番環境上でmaster.keyを作成します

[ec2-user@ip-172-31-23-189 config]$ vi master.key
# ローカル環境のmaster.keyの値を入力
fsdgagaf08deg424~~~~~

画像だと下記のような画面になります。

スクリーンショット 2020-01-18 18.20.47.png
『 i 』を押すと----INSERT-----と表示がされて、文字入力ができます。
ここにコピーしたローカルのmaster.keyの値を貼り付けします。

『 esc 』ボタンを押した入力モードを終了
『 :wq 』入力して保存します

これで本番環境でもmaster.keyが設定されています。

ユニコーンを起動

[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/[リポジトリ]
[ec2-user@ip-172-31-23-189 <app名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D

エラーが発生した場合

can't find gem bundler (>= 0.a) with executable bundle

can't find gem bundler (>= 0.a) with executable bundle 対応

原因:bundlerのバージョンが、gitcloneしたAppとEC2で異なるため失敗している。
解決策

ローカルのbundlerを確認
$ bundle -v
Bundler version 2.0.2

これで2.0.2のバージョンを利用しているとわかる。

EC2
[ec2-user@ip-172-31-23-189 <app名>]$ gem install bundler -v 2.0.2

これで最後にbundle installをして完了

EC2
[ec2-user@ip-172-31-23-189 <app名>]$ bundle install

Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

Mysql2::Error: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock'というエラーが起こった場合、mysqlが起動していない可能性があります。

ターミナル(EC2)
sudo service mysqld start

#再起動をさせたい場合は、
sudo service mysqld restart

Can't connect to local MySQL server through socket '/tmp/mysql.sock' (13)

database.ymlとcredentials.ymlの中身に漏れがないか確認をしてください

credentials.yml
db:
  database: アプリ名
  username: root
  password: 設定したPW
  socket: /var/lib/mysql/mysql.sock
config/database.yml
production:
  <<: *default
  database: <%= Rails.application.credentials.db[:database] %>
  username: <%= Rails.application.credentials.db[:username] %>
  password: <%= Rails.application.credentials.db[:password] %>
  socket: <%= Rails.application.credentials.db[:socket] %>
 #ここのsocketが抜けていないか???

サイトにアクセスしてみる

ブラウザで http://<サーバに紐付けたElastic IP>:3000/ にアクセスしてみましょう
ブラウザにCSSの反映されていない(ビューが崩れている)画面が表示されていれば成功です。

アセットコンパイルする

レイアウトが崩れてしまっているでしょう。

開発中には正常に表示されていたのに、本番ではうまく表示されないのはなぜでしょうか?

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

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <アプリ名>]$ rails assets:precompile RAILS_ENV=production
成功した場合
Yarn executable was not detected in the system.
Download Yarn at https://yarnpkg.com/en/docs/install
I, [2020-01-18T12:51:01.4345644 #1265]  INFO -- : Writing /var/app/web-share/public/assets/member_photo_noimage_thumb-224a733c50d48aba6d9fdaded809788bbeb5ea5f6d6b8368adaebb95e58bcf53.png
I, [2020-01-18T12:51:02.2615123#1265]  INFO -- : Writing /var/app/appname/public/assets/application-bc071e28a78e2b63c9313afed5ad3476e00e3f0e5b12445c37214d1f1317be48.js
I, [2020-01-18T12:51:02.2626434 #1265]  INFO -- : Writing /var/app/appname/public/assets/application-bc071e28a78e2b63c9313afed5ad3476e00e3f0e5b12445c37214d1f1317be48.js.gz
I, [2020-01-18T12:51:08.484546 #1265]  INFO -- : Writing /var/app/appname/public/assets/application-8549fb9a804686e593d5c0f90a2412a39de85908e5fb58fdf6681d4b0073d891.css
I, [2020-01-18T12:51:08.485454 #1265]  INFO -- : Writing /var/app/appname/public/assets/application-8549fb9a804686e593d5c0f90a2412a39de85908e5fb58fdf6681d4b0073d891.css.gz

エラーが出る場合

ActiveRecord::AdapterNotSpecified: 'production' database is not configured. Available: ["default", "development", "test", "database", "username", "password", "socket"]

下記を修正してください

config/database.yml
production:
  <<: *default # ここが抜けているはず
  database: <%= Rails.application.credentials.db[:database] %>
  username: <%= Rails.application.credentials.db[:username] %>
  password: <%= Rails.application.credentials.db[:password] %>
  socket: <%= Rails.application.credentials.db[:socket] %>

追記したら

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <アプリ名>] git pull origin master

再度

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <アプリ名>]$ rails assets:precompile RAILS_ENV=production

今度は成功するはずです

成功した場合
Yarn executable was not detected in the system.
Download Yarn at https://yarnpkg.com/en/docs/install
I, [2020-01-18T12:51:01.4345644 #1265]  INFO -- : Writing /var/app/web-share/public/assets/member_photo_noimage_thumb-224a733c50d48aba6d9fdaded809788bbeb5ea5f6d6b8368adaebb95e58bcf53.png
I, [2020-01-18T12:51:02.2615123#1265]  INFO -- : Writing /var/app/appname/public/assets/application-bc071e28a78e2b63c9313afed5ad3476e00e3f0e5b12445c37214d1f1317be48.js
I, [2020-01-18T12:51:02.2626434 #1265]  INFO -- : Writing /var/app/appname/public/assets/application-bc071e28a78e2b63c9313afed5ad3476e00e3f0e5b12445c37214d1f1317be48.js.gz
I, [2020-01-18T12:51:08.484546 #1265]  INFO -- : Writing /var/app/appname/public/assets/application-8549fb9a804686e593d5c0f90a2412a39de85908e5fb58fdf6681d4b0073d891.css
I, [2020-01-18T12:51:08.485454 #1265]  INFO -- : Writing /var/app/appname/public/assets/application-8549fb9a804686e593d5c0f90a2412a39de85908e5fb58fdf6681d4b0073d891.css.gz

Railsの再起動

コンパイルが成功したら反映を確認するため、Railsを再起動します。しかし、まずは今動いているUnicornをストップします。

EC2のターミナルから以下のように入力します。「aux」と打っているのは、psコマンドのオプションです。表示結果を見やすくしてくれます。また、| grep unicornとしているのはpsコマンドの結果から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のプロセス本体です。この時のPIDは、17877となっています。

[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのPID>

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

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

[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

3つあった項目が一つになっています

では、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/ にアクセスしてみましょう。今度はレイアウト崩れも無くサイトが正常に表示されていることでしょう。

参考

【Rails5.2】credentials.yml.encとmaster.keyでのデプロイによる今までとの変更点
【備忘録】credentials.yml.encにdatabase設定を保存する

Nginxのインストールと設定

Nginx

Webサーバの一種であるNginxの導入と設定を行います。
nginxは静的コンテンツ(つまりサーバ上のファイル)を高速に配信するように設計されている。
ユーザーのリクエストに対して静的コンテンツの取り出し処理を行い、そして動的コンテンツの生成をアプリケーションサーバに依頼することが可能

Nginxをインストール

下記のコマンドでインストール

[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install nginx

Nginxの設定ファイルを編集

Nginxにアクセスされたときの動作を記載する設定ファイルを作成する。
設定ファイルは、/etc/nginx/conf.dフォルダ配下に作成する。拡張子が.confのものがすべて読み込まれる設定になっている。
https://koooza.net/post-382

[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf

下記を貼り付ける
(ディレクトリの場所などは、自分にあった場所を指定してください)

rails.conf
upstream app_server {
  # Unicornと連携させるための設定。
  # アプリケーション名を自身のアプリ名に書き換えることに注意。今回であればおそらく
  server unix:/var/〇〇〇(アプリをまとめているディレクトリ)/〇〇〇〇〇〇<アプリケーション名>/tmp/sockets/unicorn.sock;
}

# {}で囲った部分をブロックと呼ぶ。サーバの設定ができる
server {
  # このプログラムが接続を受け付けるポート番号
  listen 80;
  # 接続を受け付けるリクエストURL ここに書いていないURLではアクセスできない
  server_name 18.〇〇〇.〇〇〇.〇〇(Elastic IP;

  # クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
  client_max_body_size 2g;

# 接続が来た際のrootディレクトリ
  root /var/www/〇〇〇〇〇<アプリケーション名>/public;

# assetsファイル(CSSやJavaScriptのファイルなど)にアクセスが来た際に適用される設定
  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}
  • 3行目の<アプリケーション名> となっている箇所は、ご自身のものに変更してください。
  • 11行目の<Elastic IP>となっている箇所も同様に、ご自身のものに変更してください。
  • 14行目の<アプリケーション名> となっている箇所は、ご自身のものに変更してください。

Nginxの権限を変更

POSTメソッドでもエラーが出ないようにするために、下記のコマンドも実行してください。

[ec2-user@ip-172-31-25-189 ~]$ cd /var/lib
[ec2-user@ip-172-31-25-189 lib]$ sudo chmod -R 775 nginx  

Nginxを再起動して設定ファイルを再読み込み

[ec2-user@ip-172-31-25-189 lib]$ cd ~
[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx restart

ローカルでunicorn.rb修正

listen 3000

↓以下のように修正

listen "#{app_path}/tmp/sockets/unicorn.sock"

Githubで変更点をpushしたら、本番環境でも反映させます。

ターミナル(EC2)
[ec2-user@ip-172-31-25-189 ~]$ cd /var/www/アプリ名
[ec2-user@ip-172-31-23-189 <アプリ名>]$ git pull origin master

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

続いて、unicorn_rails master(一番上)のプロセスをkillします。

[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのPID(上のコードでは17877)>

unicornを起動します

[ec2-user@ip-172-31-23-189 <アプリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D

ブラウザからElastic IPでアクセス

https:// (Elastic IP)

これでサイトが表示されず、下記が表示されたら、、、、、、、、、

スクリーンショット 2020-01-18 23.50.33.png

もう一度、下記をやり直してください。

Nginxの設定ファイルを編集

[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf

下記を貼り付ける
(ディレクトリの場所などは、自分にあった場所を指定してください)

rails.conf
upstream app_server {
  # Unicornと連携させるための設定。
  # アプリケーション名を自身のアプリ名に書き換えることに注意。今回であればおそらく
  server unix:/var/〇〇〇(アプリをまとめているディレクトリ)/〇〇〇〇〇〇<アプリケーション名>/tmp/sockets/unicorn.sock;
}

# {}で囲った部分をブロックと呼ぶ。サーバの設定ができる
server {
  # このプログラムが接続を受け付けるポート番号
  listen 80;
  # 接続を受け付けるリクエストURL ここに書いていないURLではアクセスできない
  server_name 18.〇〇〇.〇〇〇.〇〇(Elastic IP;

  # クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
  client_max_body_size 2g;

# 接続が来た際のrootディレクトリ
  root /var/www/〇〇〇〇〇<アプリケーション名>/public;

# assetsファイル(CSSやJavaScriptのファイルなど)にアクセスが来た際に適用される設定
  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}

これで無事にサイトが表示されたら、完了です!

capistranoとは?からインストール、自動デプロイ

自動でデプロイさせて負担を軽減する

デプロイの作業は非常に手間です。
いちいちその作業をすれば、随分な時間が取られてしまいます。
煩わしいので、自動化させましょう

これまでのデプロイまでの流れを振り返る

ここまでデプロイするための作業をしましたが、簡単に流れを振り返りましょう
1. git push
2. git pull
3. SSH接続
4. アセットコンパイル
5. Unicorn再起動

この一連の流れをすれば、デプロイが完了されます。
なお、この一連の流れをまだしたことがない、自信がないという人は
詳しく解説している下記の記事を閲覧してください。

EC2インスタンスを立ち上げるまでの記事はシリーズ化しているので、こちらをどうぞ
独学ではじめてAWSのEC2にデプロイする方法①~⑩(インスタンスの作成)

capistranoとは

この一連のデプロイ作業を自動化させる、様々のツールの一つにcapistranoがあります。
capistranoを利用することでサーバーにログインしなくても"" コマンド一つで ””デプロイできちゃうのですから、非常に楽です。

一度Capistranoにデプロイが成功すれば、簡略してエラーなしにデプロイができます。

Capistranoの導入

Gemのインストール

ローカルのwebappにCapistranoのgemを追加しましょう

Gemfile(ローカル)
group :development, :test do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
end

続いて、インストールします

$ bundle install

gemがインストールできたところで、Capistranoの下記のコマンドを実施

$ bundle exec cap install

するとファイルが作成されます。

railsルート
├─  Capfile
├─  config
│ ├─  deploy
│ │ ├─production.rb
│ │ └─staging.rb
│ └─deploy.rb
└─  lib
    └─capistrano
        └─tasks

これらのファイル説明は作業しながら学びましょう

Capfileを編集

一度ファイルの中身を全部消して、下記のように編集しましょう

Capfile
require "capistrano/setup"
require "capistrano/deploy"
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'

Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

production.rbを編集

production.rbですが2つファイルがあります

❌ config/environment/production.rb
⭕️ config/deploy/production.rb

今回作業はするのはconfig/deploy/production.rbです
実際に開くと下記の画面が出ます。
スクリーンショット 2020-01-19 23.44.01.png

このファイルを下記を追記しましょう!(元が全部コメントアウトなので、どこでも可能)

config/deploy/production.rb
server '18.○○○.○○.○○○(Elastic IP)', user: 'ec2-user', roles: %w{app db web}

deploy.rbを編集

config/deploy.rbを開くと下記の画面が出ます
スクリーンショット 2020-01-19 23.54.26.png

deploy.rbの記述をすべて削除
スクリーンショット 2020-01-19 23.55.21.png

下記を追加します

config/deploy.rb
# config valid only for current version of Capistrano
# capistranoのバージョンを記載。固定のバージョンを利用し続け、バージョン変更によるトラブルを防止する
lock '○.○○.○(Capistranoのバージョン)'

# Capistranoのログの表示に利用する
set :application, '○○○(自身のアプリケーション名)'
set :deploy_to, '/var/○○○(アプリを入れているディレクトリ)/○○○(アプリ名)'

# どのリポジトリからアプリをpullするかを指定する
set :repo_url,  'git@github.com:○○○(Githubのユーザー名)/○○○(レポジトリ名.git'

# バージョンが変わっても共通で参照するディレクトリを指定
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

set :rbenv_type, :user
set :rbenv_ruby, '○.○.○(rubyのバージョン)' #カリキュラム通りに進めた場合、2.5.1か2.3.1です

# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
                  keys: ['~/.ssh/○○○○○.pem(ローカルPCのEC2インスタンスのSSH鍵(pem)へのパス 例:~/.ssh/key_pem.pem))'] 

# プロセス番号を記載したファイルの場所
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }

# Unicornの設定ファイルの場所
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

# デプロイ処理が終わった後、Unicornを再起動するための記述
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end
end

貼り付けたテンプレートの一部を修正しましょう

config/deploy.rb
lock '<Capistranoのバージョン>'

Capistranoのバージョンを確認するために、Gemfile.lockを開きましょう

Gemfile.lock
    capistrano (3.11.1)
      airbrussh (>= 1.0.0)
      i18n
      rake (>= 10.0.0)
      sshkit (>= 1.9.0)

これでCapistranoのバージョンが(3.11.1)とわかりました。
ではdeploy.rbを修正しましょう

config/deploy.rb
lock '3.11.1'

rubyのバージョン確認

set :rbenv_ruby, '○.○.○(rubyのバージョン)'

ターミナルで下記を実行しましょう

$ ruby -v

> ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin18]

○○○のところは、アプリ名などを入れる必要があるので、穴埋めしてください

deproy.rb
set :application, '○○○(自身のアプリケーション名)'
set :repo_url,  'git@github.com:○○○(Githubのユーザー名)/○○○(レポジトリ名.git'
keys: ['~/.ssh/○○○○○.pem(ローカルPCのEC2インスタンスのSSH鍵(pem)へのパス 例:~/.ssh/key_pem.pem))'] 

unicorn.rbを編集

unicorn.rb
app_path = File.expand_path('../../', __FILE__)

worker_processes 1

working_directory app_path
pid "#{app_path}/tmp/pids/unicorn.pid"
listen "#{app_path}/tmp/sockets/unicorn.sock"
stderr_path "#{app_path}/log/unicorn.stderr.log"
stdout_path "#{app_path}/log/unicorn.stdout.log"

上記のunicorn.rbの記述を下記に変更

unicorn.rb
# ../が一つ増えている
app_path = File.expand_path('../../../', __FILE__)

worker_processes 1
# currentを指定
working_directory "#{app_path}/current"

# それぞれ、sharedの中を参照するよう変更
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
pid "#{app_path}/shared/tmp/pids/unicorn.pid"
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"

Nginxの設定ファイルを編集

ターミナル(EC2)
ec2-user@ip-17-242-2-2 アプリ名$ sudo vim /etc/nginx/conf.d/rails.conf

そして、capistranoに合わせた参照先に変更します。(詳細はコメントアウトで解説しています。)

rails.conf
upstream app_server {
  # sharedの中を参照するよう変更(/shared/tmp/sockets/unicorn.sock;)
  server unix:/var/○○○(アプリをまとめているディレクトリ)/○○○○○(アプリケーション名)/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name 18.○○○.○○(Elastic IP;

  # currentの中を参照するよう変更(/current/public;)
  root /var/○○○(アプリをまとめているディレクトリ)/○○○○○(アプリケーション名)/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    # currentの中を参照するよう変更(/current/public;)
    root   /var/○○○/○○○○○○(アプリケーション名)/current/public;
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}

Nginxの設定を変更したら、忘れずに再読込・再起動

[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx reload
[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx restart

MySQLの起動を確認

ターミナル(EC2)
[ec2-user@ip-172-31-25-189 ~]$ sudo service mysqld restart

unicornのプロセスをkillしよう

ターミナル(EC2)
[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

一番上のunicorn_rails masterをkillしたいので、下記を実施

[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill 17877

ローカルでの修正を全てmasterにpushしてください

自動デプロイの実施

# アプリケーションのディレクトリで実行する
$ bundle exec cap production deploy

すると下記ん画像のように、徐々に処理が進み出す。
Image from Gyazo

エラーが発生する場合

ディレクトリ `/var/www' を作成できません: 許可がありません

Image from Gyazo

mkdir stdout: Nothing written
mkdir stderr: mkdir: ディレクトリ `/var/www' を作成できません: 許可がありません
mkdir: ディレクトリ `/var/www' を作成できません: 許可がありません

ヒヤリング:手動デプロイはできていたか?
・YES:Capistranoの設定の問題(ここまで進めている以上、できているはず)
・NO:もう一度手動デプロイを確認する必要があるかもしれません。

設定の見直し

rails.confとdeploy.rbのパスの確認をしてください。

var/www/アプリ名で設定しているか?
・ディレクトリはwwwの場合、入力間違いがないか???
・ディレクトリは"wwwでない"場合、capistranoのデフォルト設定を変更する必要がある。
EC2でのアプリの保存場所が『 var/www/アプリ名 』でない場合、、

[参考](https://capistranorb.com/documentation/getting-started/configuration/)

deplory.rbに下記を追加してください。

deploy.rb
set :deploy_to, '/var/○○○/アプリ名'

capistranoのデフォルト設定では、/var/www/アプリ名が設定されているため、これを変更する必要がある。
そのオプション設定がset :deploy_to, '/var/○○○/アプリ名'である。

Master.keyがないエラー( Missing encryption key to decrypt file with. Ask your team for your master key and write it to )

このエラーが表示されたということは、『 本番環境にあるmaster.keyをうまく読み込めていない 』ことを意味します。

rake stdout: Nothing written
rake stderr: Missing encryption key to decrypt file with. Ask your team for your master key and write it to /var/○○○(アプリを格納しているディレクトリ名)/○○○(アプリ名)/releases/20200121124714/config/master.key or put it in the ENV['RAILS_MASTER_KEY'].

なので現状として可能性は二つです。

  • master.keyを作成していない。
  • master.keyを作成する場所が間違っている。

ここまで作業を進めている人は,master.keyを作成しているはずです。
>つまり、master.keyの作成場所をまちがている可能性が高いです。

# 誤解が生まれやすいmaster.keyの作成場所

✖︎ アプリ名>config>master.key
○ アプリ名>shared>config>master.key

おそらく、上記のようにmaster.keyの作成場所に誤りがある可能性が高いです。
ですから、

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ cd shared 
[ec2-user@ip-172-31-23-189 shared ]$ cd config
[ec2-user@ip-172-31-23-189 config ]$ ls
>ここでmaster.keyがない場合、 master.keyを作成してください。

master.keyを作成する場合、、、

ターミナル(ローカル)
アプリ名 $ vi config/master.key
>master.keyを中身がわかります。
>間違っても編集しないようにしましょう

ローカル環境のmaster.keyをコピーしたら、EC2にmaster.keyを作成しましょう

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ cd shared/config
[ec2-user@ip-172-31-23-189 config ]$ vi master.key
>編集画面が出るので
>ローカルのmaster.keyをコピペします。
>:wpで保存しましょう

master.keyを読み込ませるために、deploy.rbに
下記を追加してください

deploy.rb
set :linked_files, fetch(:linked_files, []).push("config/master.key")

再度自動デプロイしましょう

# アプリケーションのディレクトリで実行する
$ bundle exec cap production deploy

今度はうまくいくはずです。

参考:Rails5.2から追加された credentials.yml.enc のキホン

mylevel
誰よりもわかりやすく端的に説明することが得意です。 記事投稿したらお知らせしますので、ぜひTwitterもフォローしてください きっとあなたの役にたちます
https://twitter.com/nousi201
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした