すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Rails

【Rails】 AWSのEC2にデプロイする方法~画像で丁寧に解説!

ぴっかちゃん
ぴっかちゃん

AWSのEC2を使ってデプロイする方法を解説します。具体的な設定方法がわからない方はぜひ参考にしてください。

Railsでアプリを作成したが、サーバーへのアップの仕方がよくわからないという方もいらっしゃるのではないでしょうか?

この記事ではAWSのEC2というサービスを使って作成したアプリのデプロイ方法を詳しく解説していきます。

webサーバーはNginxを、アプリケーションサーバーはUnicornを使用します。

EC2とは?

ec2

EC2とは通販で有名なAmazonが提供しているクラウドコンピューティングサービスであるAWSの中のサービスの一つです。
EC2についての詳しい説明はこちらの記事を参照ください。

EC2の設定をしよう

この章ではEC2の設定方法を紹介していきます。
まずはAWS公式サイトの新規登録ページで登録をしましょう。

全てを入力して「続行」をクリックします。

AWSにサインアップ

次に連絡先を入力し「続行」をクリックします。
住所はローマ字で入力します。

住所登録

次は請求情報を入力します。

請求情報

次に本人確認を行います。

本人確認

そして選んだ受け取り方法で送られる数字を入力します。

本人確認

最後にサポートプランを選択します。
まずはベーシックプランを選択しておくのが良いでしょう。

サポートプランを選択

これで登録は完了です。

登録完了

続いて「AWSマネジメントコンソールへ進む」をクリックします。
するとサインイン画面になるので、ルートユーザーとしてサインインしましょう。

サインイン

このようにマネジメントコンソールが表示されます。

マネジメントコンソール

この時リージョンが「東京」以外になっていた場合は「東京」にしておきましょう。

「全てのサービス」を選択すると「コンピューティング」の中にEC2があるのでクリックします。

EC2の選択

クリック後、このような画面になれば準備OKです。

EC2ダッシュボード

インスタンスを作成しよう

それでは実際にインスタンスを作成していきましょう。
ダッシュボードから「インスタンスを起動」をクリックします。

インスタンスを起動

AMIを選択しよう

するとAmazonマシンイメージ(AMI)を選択する画面になります。
ここでは「Amazon Linux 2 AMI」を選択しておきましょう。

AMI

インスタンスタイプを選択しよう

次はインスタンスタイプの選択です。
今回は練習なので無料枠で利用できるt2.microを選択します。
選択されているのが確認できたら「次のステップ:インスタンスの詳細の設定」をクリックします。

インスタンスタイプ

次にインスタンスの詳細の設定画面になりますが、ここでは何も設定はせずに「次のステップ:ストレージの追加」をクリックします。

詳細設定

ストレージを追加しよう

次はストレージの追加を行います。
ストレージとはインスタンスに紐づいたハードディスクのようなものです。
サイズはデフォルトだと8GiBですが、無料枠だと30GiBまで無料なので30に変更しておきましょう。
その後、「次のステップ :タグの追加」をクリックします。

ストレージの追加

タグを設定しよう

続いてインスタンスを管理しやすくするためにタグを設定します。
タグの詳細についてはAWS公式「Amazon EC2 リソースのタグ付け」を参照してください。

「タグの追加」をクリックするとキーと値を入力できます。

タグの追加

今回はキーには「Name」、値にはこれから公開するプロジェクトの名前を入力しておきましょう。

タグの追加

入力が終わったら「次のステップ:セキュリティグループの設定」をクリックします。
するとセキュリティグループの設定画面になりますが、今回は何も編集せずこのまま「確認と作成」をクリックしましょう。

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

するとこのように確認画面が表示されます。

確認画面

上部に「インスタンスのセキュリティを強化してください。 セキュリティグループ launch-wizard-1 は世界に向けて開かれています。」という警告文が表示されますが、今回これは気にしなくても大丈夫です。

キーペアをダウンロードしよう

「起動」をクリックするとキーペアの作成画面になります。
キーペアとはインスタンスへの接続時に身分証明に使用するセキュリティ認証情報のセットであり、プライベートキーパブリックキーで構成されます。
パブリックキーは Amazon EC2 が保存し、プライベートキーはユーザーが保存します。
※参照:AWS公式「Amazon EC2 キーペアと Linux インスタンス」

まだキーペアは作成していないので「新しいキーペアの作成」を選択します。

新しいキーペアの作成

キーペア名にわかりやすい名前をつけて「キーペアのダウンロード」をクリックします。

キーペアのダウンロード

これでプライベートキーを取得することができました。
先ほど記述した通りプライベートキーはインスタンスに接続するための大事な鍵となります。
無くさないように自分のPCに保存し、決して他人には渡さないようにしましょう。

キーペアをダウンロードすると「インスタンスの作成」をクリックできるようになるのでクリックし、インスタンスを作成します。

インスタンスの作成

下のような画面になればインスタンが無事に作成できています。

作成ステータス

右下の「インスタンスの表示」をクリックし、作成したインスタンスを確認してみましょう。

インスタンスの表示

SSH接続をしよう

それでは作成したインスタンスにSSH接続してみましょう。
接続するには先ほどダウンロードしたプライベートキーが必要になります。

MacであればDownloadsフォルダに拡張子がpemのファイルがあるはずです。
このファイルはEC2インスタンスに接続するために必要な非常に大事なファイルなので.sshのようなディレクトリを作成してその中に保存しておきましょう。

ターミナル | .sshディレクトリの作成
1
2
3
4
5
# .sshディレクトリの作成
% mkdir ~/.ssh

# pemファイルの移動
% mv Downloads/プライベートキーの名前.pem .ssh/

これからは.sshというディレクトリにプライベートキーがあるとして解説していきます。

秘密鍵の権限を変更しよう

このままの状態でSSH接続すると警告メッセージが出ます。

ターミナル | 警告メッセージ
1
2
3
4
5
6
7
8
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'pikawaka.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "pikawaka.pem": bad permissions
ec2-user@54.12.3.45: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

これは「プライベートキーのアクセス権限が644になっていて他のユーザーからもアクセス可能な状態だからアクセスできないようにする必要があるよ」というメッセージです。
ですのでプライベートキーのアクセス権限を変更し、自分だけが読み込みできるようにしておきます。

ターミナル | アクセス権限の変更
1
2
3
4
5
# .sshディレクトリに移動
% cd ~/.ssh

# 権限の変更
% chmod 400 プライベートキーの名前.pem

sshコマンドでログインしよう

カレントディレクトリが.sshの状態で下記のコマンドを実行するとインスタンスと接続することができます。

ターミナル | SSH接続
1
% ssh -i プライベートキーの名前.pem ec2-user@パブリックIPv4アドレス

パブリックIPv4アドレスはインスタンスの表示のページで確認ができます。

インスタンスの表示

それでは実際にコマンドを入力してみましょう。
今回のコマンドは下の例の場合なので、実際はご自身のものを入力してください。

(例)
プライベートキーの名前: pikawaka.pem
パブリックIPv4アドレス: 54.12.3.45

ターミナル | SSH接続
1
2
% cd ~/.ssh
% ssh -i pikawaka.pem ec2-user@54.12.3.45

コマンドを実行し、下記のような警告メッセージが出たらyseと入力しenterキーを押しましょう。

ターミナル | 警告メッセージ
1
2
3
The authenticity of host '54.12.3.45 (54.12.3.45)' can't be established.
ECDSA key fingerprint is SHA256:WyV3fw1iEiBKslM0/m95UCq75kDBULrKi8W71+Ay9Tk.
Are you sure you want to continue connecting (yes/no)? 

下記のように出力されれば無事EC2に接続完了です。

ターミナル | SSH接続
1
2
3
4
5
6
ssh -i pikawaka.pem ec2-user@54.12.3.45
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/

ターミナルでの表示も自分のPCではなくEC2インスタンスに変わっています。
※数字の部分は人によって異なります。

ターミナル | ターミナルの確認
1
[ec2-user@ip-172-12-34-5 ~]$

ログアウトするにはexitと入力します。

ターミナル | ログアウト
1
2
3
[ec2-user@ip-172-12-34-5 ~]$ exit
ログアウト
Connection to 54.12.3.45 closed.

Elastic IPを紐付けよう

以上のような流れでEC2に接続できました。
次回以降も接続するには先ほどのコマンドを実行します。

ですがインスタンスを停止し、再度起動するとパブリックIPv4アドレスが変更されてしまいます。
これだと不便なのでElastic IPという固定されたパブリックIPアドレスを使用します。

EC2のダッシュボードのメニューから「Elastic IP」をクリックします。
その後に表示されるページで「Elastic IP アドレスの割り当て」をクリックします。

Elastic IP

次のページでは「パブリックIPv4アドレスプール」で`AmazonのIPv4アドレスプールが選択されているのを確認できたら右下にある「割り当て」をクリックします。

割り当て

次にElastic IPの関連付けを行います。
表示されているページの「アクション」をクリックし、「Elastic IPアドレスの関連付け」をクリックします。

アドレスの関連付け

次にインスタンスタイプの選択から関連付けるインスタンスを選択し、「関連付ける」をクリックします。

関連付け

その後、このような画面になれば関連付けが完了です。

関連付け完了

実際に関連付けられているか、ダッシュボードの「インスタンス」をクリックし、確認したいインスタンスを選択してみましょう。

インスタンスの確認

下の画像のようにElastic IPアドレスが表示されていればOKです。

確認画面

今後はこのElastic IPアドレスをSSH接続の際に使用します。

Elastic IPアドレスの料金について

次の条件がすべて満たされている限り、Elastic IPアドレスを無料で1つ取得できます。

  • Elastic IP アドレスが EC2 インスタンスに関連付けられている。
  • Elastic IP アドレスに関連付けられているインスタンスが実行中である。
  • インスタンスには、1 つの Elastic IP アドレスしかアタッチされていない。
  • Elastic IP アドレスは、Network Load Balancer や NAT ゲートウェイなどのアタッチされたネットワークインターフェイスに関連付けられます。

つまり1つのElastic IPアドレスに関連付けたインスタンスが起動していれば料金は発生しません。
次の場合は0.005 USD/時間の料金が発生してしまうので注意しましょう。

  • インスタンスに関連付けられていないElastic IPアドレスがある
  • Elastic IPアドレスが関連付けられているインスタンスを停止する
  • 2つ以上のElastic IPアドレスを作成する

※参照:AWS公式「Elastic IPアドレス」

ログインを簡単にしよう

今後インスタンスに接続する際は先ほどのコマンドを実行しますが、毎回このコマンドを実行する際にはElastic IPアドレスの値を確認したり、覚えておく必要があるので面倒です。
ですので、あらかじめ設定をしておきログインを簡単にします。

ターミナルで下記のコマンドを実行します。

ターミナル | configの編集
1
2
% cd ~/.ssh
% vi config

するとconfigの中身が表示されます。
ここに書き込みを行うのでiを押しINSERTモードにします。

その後、下記のコードを入力します。

ターミナル | configの編集
1
2
3
4
Host 接続先名
  HostName Elastic IPアドレス
  User ec2-user
  IdentityFile ~/.ssh/プライベートキーの名前.pem

「接続先名」は任意のわかりやすい名前を入れましょう。
Elastic IPアドレスは先ほどの画面で確認ができます。
「IdentityFile」は鍵を指定します。

ターミナル | configの編集
1
2
3
4
5
# 書き方の例
Host pikawaka
  HostName 54.123.45.678
  User ec2-user
  IdentityFile ~/.ssh/pikawaka.pem

入力が完了したらescキーを押しINSERTモードから抜けます。
その後、:wqと入力します。
これで設定は完了です。

これで下記のコマンドを実行するだけで接続できるようになりました。
コマンドを打つ際はカレントディレクトリを.sshにする必要はありません。

ターミナル | 接続コマンド
1
2
3
4
% ssh 接続先名

# 接続先名がpikawakaの場合
% ssh pikawaka

コマンド実行後、最初に表示された警告メッセージが表示されたら同じようにyesと入力してください。

1
2
3
4
# file: ターミナル | 警告メッセージ
The authenticity of host '54.123.45.678 (54.123.45.678)' can't be established.
ECDSA key fingerprint is SHA256:WyV3fw1iEqBKslM0/m95UCq75kDBULrKi8W71+Ay9Tk.
Are you sure you want to continue connecting (yes/no)?

先ほどのコードが出力されればOKです。

ターミナル | 接続の確認
1
2
3
4
5
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/

▼ AWSの用語や技術について不安がある方は、初心者向けに図解を使って丁寧に解説している以下の参考書を利用すると良いでしょう。クラウドやネットワークの基礎から学べます!

aws参考書
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

IT業界などへの転職・就職を目指す人、駆け出しエンジニアがAWS関連の用語、しくみ、クラウドとネットワークの基礎技術などを一通り学べます。

作成したインスタンスの環境構築をしよう

これでEC2インスタンスに接続できるようになりました。
接続したインスタンスは新しいパソコンを買ってきた直後のように何もインストールされておりません。
ですのでこれからRailsで作成したアプリを動かせるように環境構築をしていきます。

この章では環境構築の流れを解説していきます。
EC2インスタンスにインストールしていくため、インスタンスに接続したターミナルでコマンドを入力していくので注意しましょう。
[ec2-user@ip-172-31-47-9 ~]$の後のコマンドを入力していきます。

パッケージをアップデートしよう

まずはパッケージをアップデートします。
パッケージとはアプリケーションを動かすためのファイルの集合体のことを指します。
複数のファイルが1つの箱に入っているようなイメージです。

パッケージのバージョンを管理するにはyumコマンドを使います。
まずはyumコマンドでパッケージをアップデートしましょう。
Is this ok [y/d/N]: yと聞かれたらyと入力しenterキーを押します。

EC2ターミナル | パッケージのアップデート
1
[ec2-user@ip-172-31-47-9 ~]$ sudo yum update

「完了しました!」と表示されればアップデートは完了です。

必要なパッケージをインストールしよう

次に必要なパッケージをインストールしていきます。
Amazon LInuxは初期状態だと必要最低限のパッケージしか入っていません。
なのでよく利用するパッケージをインストールしていきます。

今回はRailsアプリが動くよう下記のパッケージをインストールします。

名前 役割
gcc-c++ c++のコンパイラ
make ソースコードからビルドできる
patch ファイルの修正や生成ができる
git バージョン管理ができる
curl データを転送できる
zlib-devel データの圧縮や伸張ができる
openssl-devel 通信を暗号化する
ImageMagick-devel 画像を操作したり表示できる
readline-devel CUIで行入力を支援してくれる
libcurl-devel curlを扱える
libffi-devel FFIの機能を扱える
libyaml-devel yamlファイルを扱える
libicu-devel Unicodeを扱える
libxml2-devel XMLを解析できる
libxslt-devel XMLにXSLを適用させる

インストールするコマンドは下記の通りです。

EC2ターミナル | パッケージのインストール
1
[ec2-user@ip-172-31-47-9 ~]$ sudo yum -y install パッケージ名

今回はこれらのパッケージを同時にインストールしましょう。
ターミナルで下記のコマンドを実行します。

EC2ターミナル | パッケージのインストール
1
2
# 横に長いので全てをコピーしてください
[ec2-user@ip-172-31-47-9 ~]$ sudo yum -y install gcc-c++ make patch git curl zlib-devel openssl-devel ImageMagick-devel readline-devel libcurl-devel libffi-devel libicu-devel libxml2-devel libxslt-devel

コマンドを実行するとそれぞれのパッケージを一度でインストールすることができます。

「完了しました!」と表示ができれば無事インストールされています。

Node.jsをインストールしよう

次にJavaScriptを実行できるよう環境を整えます。
まずはNode.jsをインストールします。

EC2ターミナル | yarnのインストール
1
2
3
4
# AWSのリポジトリに追加
[ec2-user@ip-172-31-47-9 ~]$ curl -sL https://rpm.nodesource.com/setup_14.x | sudo bash -
# インストール
[ec2-user@ip-172-31-47-9 ~]$ sudo yum -y install nodejs

コマンド実行後、「完了しました!」と表示されば無事インストールされています。

yarnをインストールしよう

Rails6以降はyarnを使うので、yarnもインストールします。
ターミナルで下記のコマンドを実行します。

EC2ターミナル | yarnのインストール
1
2
3
4
# AWSのリポジトリに追加
[ec2-user@ip-172-31-47-9 ~]$ curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
# インストール
[ec2-user@ip-172-31-47-9 ~]$ sudo yum -y install yarn

コマンド実行後、「完了しました!」と表示されば無事インストールされています。

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

次はrubyのバージョン管理ツールであるrbenvをインストールします。
下記のコマンドを実行します。

EC2ターミナル | rbenvのインストール
1
2
3
4
5
6
# レポジトリをクローンしてインストール
[ec2-user@ip-172-31-47-9 ~]$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
# .bash_profileの設定
[ec2-user@ip-172-31-47-9 ~]$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
[ec2-user@ip-172-31-47-9 ~]$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
[ec2-user@ip-172-31-47-9 ~]$ source .bash_profile

次はrubyをインストールするためのruby-buildをインストールします。

EC2ターミナル | ruby-buildのインストール
1
[ec2-user@ip-172-31-47-9 ~]$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

これでrubyをインストールできるようになりました。

rubyをインストールしよう

次はrubyをインストールします。
今回はバージョン2.6.5をインストールしますが、バージョンはご自身の環境に合わせてください。
下記のコマンドを実行します。

インストール中はInstalling ruby-2.6.5...と表示されます。
インストールには数分かかるので、このままインストールが完了するまで待ちましょう。
完了するとInstalled ruby-2.6.5 to /home/ec2-user/.rbenv/versions/2.6.5と表示されます。

EC2ターミナル | rubyのインストール
1
2
3
4
5
6
# rubyのインストール
[ec2-user@ip-172-31-47-9 ~]$ rbenv install 2.6.5
# 実行中の表示
Installing ruby-2.6.5...
# 完了後に表示
Installed ruby-2.6.5 to /home/ec2-user/.rbenv/versions/2.6.5

次はインストールしたrubyを使用可能にするコマンドを実行します。

EC2ターミナル | rubyのインストール
1
2
3
4
# インストールしたrubyを使用可能にする
[ec2-user@ip-172-31-47-9 ~]$ rbenv rehash
# このインスタンスで使用するバージョンの設定
[ec2-user@ip-172-31-47-9 ~]$ rbenv global 2.6.5

下記のコマンドを実行し、インストールしたバージョンが表示されればOKです。

EC2ターミナル | バージョンの確認
1
2
[ec2-user@ip-172-31-47-9 ~]$ ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]

データベースの設定をしよう

次はデータベースを設定していきます。
今回はリレーショナルデータベースの一つであるMySqlを使います。

Amazon Linux 2 にはMySql派生として開発され、MySqlとほぼ同様に扱えるMariaDBのライブラリがデフォルトで入っているので、こちらを使用します。

MariaDBをインストールしよう

まずはMariaDBとMySqlをインストールします。

EC2ターミナル | MariaDBのインストール
1
[ec2-user@ip-172-31-47-9 ~]$ sudo yum -y install mariadb-server mysql-devel

「完了しました!」と表示されればOKです。

データベースを起動しよう

続いてデーターベースを起動させます。

EC2ターミナル | データベースの起動
1
[ec2-user@ip-172-31-47-9 ~]$ sudo systemctl start mariadb

コマンドを入力しても何も出力されないので、下記のコマンドで状態を確認してみます。

EC2ターミナル | 状態の確認
1
2
3
4
5
[ec2-user@ip-172-31-47-9 ~]$ sudo systemctl status mariadb
● mariadb.service - MariaDB database server
   Loaded: loaded (/usr/lib/systemd/system/mariadb.service; disabled; vendor preset: disabled)
   Active: active (running) since 火 2021-05-25 01:22:41 UTC; 1min 53s ago
  Process: 22975 ExecStartPost=/usr/libexec/mariadb-wait-ready $MAINPID (code=exited, status=0/SUCCESS)

このようにactive (running)と表示されていれば問題なく起動できています。

セキュリティ設定を設定しよう

次にrootパスワードなどのセキュリティ設定をします。
パスワードを設定する箇所では入力した文字が表示されませんが、入力されているので気をつけましょう。

EC2ターミナル | セキュリティ設定
1
2
3
4
5
6
7
8
9
10
[ec2-user@ip-172-31-47-9 ~]$ sudo mysql_secure_installation
# 下のメッセージが出たらenterキーを押す
Enter current password for root (enter for none):
# 下のメッセージが出たらyと入力し、enterキーを押す
Set root password? [Y/n]
# 下のメッセージが出たら設定するパスワードを入力しenterキーを押す
New password:
# 下のメッセージが出たら設定したパスワードを入力しenterキーを押す
Re-enter new password:
# 以降の問いには全てyで答えましょう

最後にAll done! If you've completed all of the above steps, your MariaDB
installation should now be secure.
と表示されれば設定完了です。

接続してみよう

それでは先ほど設定したパスワードで接続できるか確認してみましょう。

EC2ターミナル | 接続の確認
1
2
3
4
5
6
7
8
9
10
11
12
[ec2-user@ip-172-31-47-9 ~]$ mysql -u root -p
# 下のメッセージが出たらパスワードを入力し、enterキーを押す
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 21
Server version: 5.5.68-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

上のように表示されていれば問題ありません。
exitと入力し、抜け出ましょう。

パスワードを忘れてしまった時

万が一パスワードを忘れてしまった時は以下の手順でコマンドを実行しましょう。

EC2ターミナル | パスワード再設定
1
2
3
4
# 一度データベースを止める
[ec2-user@ip-172-31-47-9 ~]$ sudo systemctl stop mariadb
# 下記のコマンドでセーフモードでデータベースを起動
[ec2-user@ip-172-31-47-9 ~]$ sudo mysqld_safe --skip-grant-tables --skip-networking &

するとmysqld_safe Starting mysqld daemon with databases from /var/lib/mysqlと表示されます。
続けて下記のコマンドを実行します。

EC2ターミナル | パスワード再設定
1
2
3
4
5
6
7
8
9
10
11
12
13
# パスワードなしで接続する
mysql -u root
# 接続メッセージが表示されたら下記のコマンドを入力
MariaDB [(none)]> UPDATE mysql.user SET Password = PASSWORD('新しいパスワード') WHERE User = 'root';
# 下の出力が出ればOK
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
# 付与テーブルを再ロード
MariaDB [(none)]> FLUSH PRIVILEGES;
# 下の出力が出ればOK
Query OK, 0 rows affected (0.00 sec)
# ariaDB モニターを終了
MariaDB [(none)]> exit

新しいパスワードを登録する部分は下記のように入力します。

(例)新しいパスワードを「pass」にする時
UPDATE mysql.user SET Password = PASSWORD('pass') WHERE User = 'root';

これでパスワードを再設定できました。
次はセーフモードで起動したサーバーのプロセスを切ります。

EC2ターミナル | プロセスのkill
1
2
3
4
5
6
[ec2-user@ip-172-31-47-9 ~]$ sudo kill `sudo cat /var/run/mariadb/mariadb.pid`
# 再度データベースを起動
[ec2-user@ip-172-31-47-9 ~]$ sudo systemctl start mariadb
# パスワードなしで入れないかの確認
[ec2-user@ip-172-31-47-9 ~]$ mysql -u root
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

これでパスワードの再設定は完了です。
新しいパスワードで接続できるか確認してみましょう。

アプリをデプロイしよう

これでデプロイをする準備が整いました。
この章ではデプロイをするまでの流れを確認していきます。

gitとの連携をしよう

EC2インスタンスにアプリケーションのコードを送るためにはGithubを使います。
連携したGithubからEC2へクローンすることでデプロイをします。
そのためにGitHubとの接続設定をします。
ターミナルで下記のコマンドを実行します。

EC2ターミナル | gitの連携
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[ec2-user@ip-172-31-47-9 ~]$ ssh-keygen -t rsa
Generating public/private rsa key pair.
# 下のコードが表示されたらenterキーを押す
Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa):
# 下のコードが表示されたらenterキーを押す
Enter passphrase (empty for no passphrase):
# 下のコードが表示されたらenterキーを押す
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:
SHA256:Bi7Ds2BBqjT1/H9Wx3Ayv9i2Nyfor9NdvmUpucGtjbs ec2-user@ip-172-31-47-9.ap-northeast-1.compute.internal
The key's randomart image is:
+---[RSA 2048]----+
|  ..             |
| o. o            |
|.o.  o.      + . |
|o .o ...      B  |
|. o = ..S    . + |
| . . = ..   o * +|
|    .    . o O O+|
|          o o @oB|
|           .oE+==|
+----[SHA256]-----+

これでid_rsa.pubというファイルに公開鍵が書き込まれました。
次にcatコマンドで中身を確認します。

EC2ターミナル | id_rsa.pubの確認
1
2
[ec2-user@ip-172-31-47-9 ~]$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAaBAQC1RYWQHGhrcXljlUGJn7Sn8VOS7HNHsVNOXc7abdLRoXsfy7Iofys5ogGzHuJxdHEG75CwlmENBcZsh5lU/Tx/5F283KPPGyK2eFqld9/LEu9Z/yTVckStgN8dnmlr6rcWnJUTyj4cjenDg1TIo57TL07vFN+a87y506a9LV0Rzr+FsAFqQ5jw9ZlO9QshT72N7Kgwv+cpCv6RMtsO6solEjbc4yijFsb+NT6Jyp0EHYXW8jK8fWKp1bUwmZYu8jSTbSr2X9snJ5eB/w78g8Ie+kl87WgLBxVjXiEdMI2PUFweskvaaXDt3fEwLhIZeUbpQh9YAU9j+wYCI7aiR4en ec2-user@ip-172-31-47-9.ap-northeast-1.compute.internal

するとssh-rsaから始まる情報が表示されます。
これら表示されている文字を最初の「ssh-rsa」から最後の「.internal」まで全てコピーしましょう。

次に自分のGitHubの登録ページから公開鍵を登録します。
上のリンク先の「New SSH key」をクリックしましょう。

ssh登録ページ

すると下記の画面になるので、Titleにはわかりやすい名前を、Keyにはコピーした公開鍵を貼り付け、「Add SSH key」をクリックします。

登録画面

最後にGitHubのパスワードを求められるので入力をしましょう。

ssh接続を使用

それではssh接続ができるかを確認してみましょう。
ターミナルで下記のコマンドを実行します。

EC2ターミナル | ssh接続の確認
1
2
3
4
5
6
7
8
[ec2-user@ip-172-31-47-9 ~]$ ssh -T git@github.com
The authenticity of host 'github.com (52.69.186.44)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
RSA key fingerprint is MD5:16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
# 確認メッセージが表示されたらyesと入力
Are you sure you want to continue connecting (yes/no)?
Warning: Permanently added 'github.com,52.12.345.67' (RSA) to the list of known hosts.
Hi GitHubユーザー名! You've successfully authenticated, but GitHub does not provide shell access.

上の最後のメッセージが表示されれば接続完了です。
Permission denied (publickey).と表示されてしまったら公開鍵が正しく設定されているか確認しましょう。
その際は一度登録したkeyを削除し、再度登録してみましょう。

削除

確認画面が出るのでクリックして削除しましょう。

確認画面

保存先のディレクトリを作成しよう

次にGitHubからクローンしてくるアプリの保存先を作成します。
下記のコマンドで保存するディレクトリを作成します。
その後、作成したディレクトリの権限をec2-userに変更をしておきます。

EC2ターミナル | 保存先の作成
1
2
[ec2-user@ip-172-31-47-9 /]$ sudo mkdir /var/www/
[ec2-user@ip-172-31-47-9 /]$ sudo chown ec2-user /var/www/

これで保存するディレクトリが作成できました。

サーバーを設定しよう

以上でGitHubからクローンをする準備ができました。
クローンしたアプリケーションを動かすには、ユーザーから送られてきたリクエストにレスポンスを返す必要があります。
この役割をサーバーが担当します。
サーバーにはwebサーバーアプリケーションサーバーがあります。

webサーバーとは

webサーバーとは静的コンテンツの処理を担当するサーバーです。例えば、ランディングページなどいつみても同じ内容のファイルを処理します。
rubyなどのプログラミングを必要とせず、htmlとcssだけで作成したサイトで使われます。

アプリケーションサーバーとは

アプリケーションサーバーはtwitterなど見るたびに内容が変わっているファイル、つまり動的コンテンツの処理を担当するサーバーです。

リクエストからレスポンスまでの流れとして、まずはwebサーバーがリクエストを確認し、自分でレスポンスを送ることができればそのままレスポンスを返します。
動的コンテンツのリクエストが送られてきたときはwebサーバーは自分で処理できないのでアプリケーションサーバーで処理してもらい、その結果をwebサーバーが返します。

Nginxの設定をしよう

まずはwebサーバーの設定から行います。
今回はNginx(エンジンエックス)というwebサーバーを使います。

Nginxをインストールしよう

下記のコマンドでNginxをインストールします。
途中でIs this ok [y/d/N]:と聞かれるのでyと入力しenterキーを押すましょう。

EC2ターミナル | Nginxのインストール
1
[ec2-user@ip-172-31-47-9 ~]$ sudo amazon-linux-extras install nginx1

バージョンを確認するコマンドでバージョンが表示できればインストールは成功しています。

EC2ターミナル | バージョンの確認
1
2
[ec2-user@ip-172-31-47-9 ~]$ nginx -v
nginx version: nginx/1.20.0

この状態でwebサーバーにアクセスしてみましょう。

その前にNginxを起動させます。

EC2ターミナル | Nginxを起動
1
[ec2-user@ip-172-31-47-9 ~]$ sudo systemctl start nginx

それではご自身のElastic IPアドレスで接続してみましょう。

http://Elastic IPアドレス
(例)
http://54.123.45.678/

httpsではなくhttpで接続するので注意です。

アクセスの確認

するとこのようにアクセスができません。
これはhttpで接続できるようにするセキュリティ設定ができていないためです。
httpでアクセスできるようにポートを解放する必要がありますので、セキュリティグループの編集を行います。

セキュリティグループの編集をしよう

EC2のダッシュボードからインスタンスをクリックし、編集したいインスタンスIDをクリックします。

インスタンス

すると下の画面になるので、「セキュリティ」を選択し、「セキュリティグループ」をクリックします。

セキュリティグループ

次に「インバウンドルール」になっているのを確認し、「インバウンドルールを編集」をクリックします。

インバウンドルールの編集

下の画面になるので「ルールを追加」をクリックします。

ルールの追加

今回はhttpのポートを解放したいのでタイプは「HTTP」を選択します。
送信元はインターネット全体にするので「0.0.0.0/0」を選択します。

編集画面

その後、「ルールを保存」をクリックします。
接続できるかどうか先ほどのアドレスで確認します。

確認

このようにNginxの初期状態のページが表示されました。

Nginxの設定ファイルを編集しよう

次はNginxにアクセスされた時の動作を設定するファイルの編集です。
それぞれの設定ファイルは/etc/nginxディレクトリに格納されています。
デフォルトの設定はnginx.confファイルで定義されています。

自分で設定ファイルを作成する際は最初から作られているnginx.conf.defaultファイルを参考に記述していきます。
それではnginx.conf.defaultファイルの中身を確認してみます。

nginx.conf.default | nginx.conf.default の中身 -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
  worker_connections  1024;
}


http {
  include       mime.types;
  default_type  application/octet-stream;

  #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
  #                  '$status $body_bytes_sent "$http_referer" '
  #                  '"$http_user_agent" "$http_x_forwarded_for"';

  #access_log  logs/access.log  main;

  sendfile        on;
  #tcp_nopush     on;

  #keepalive_timeout  0;
  keepalive_timeout  65;

  #gzip  on;

  server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;

    #access_log  logs/host.access.log  main;

    location / {
      root   html;
      index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #  proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
  }


  # another virtual host using mix of IP-, name-, and port-based configuration
  #
  #server {
  #  listen       8000;
  #  listen       somename:8080;
  #  server_name  somename  alias  another.alias;

  #  location / {
  #    root   html;
  #    index  index.html index.htm;
  #  }
  #}


  # HTTPS server
  #
  #server {
  #  listen       443 ssl;
  #  server_name  localhost;

  #  ssl_certificate      cert.pem;
  #  ssl_certificate_key  cert.key;

  #  ssl_session_cache    shared:SSL:1m;
  #  ssl_session_timeout  5m;

  #  ssl_ciphers  HIGH:!aNULL:!MD5;
  #  ssl_prefer_server_ciphers  on;
  #  location / {
  #    root   html;
  #    index  index.html index.htm;
  #  }
  #}

}

これを参考にRails用の設定ファイルを作成して編集していきます。

設定は設定項目 設定値;のように記述します。

上のファイルに出てくるものと、これから作成するファールで使う設定項目の一部を解説します。

設定項目 設定値
server サーバー情報を定義
listen 接続を許可するポート番号やIPアドレスを定義
server_name アクセスを受け付けるURL
location ロケーションの指定
root アプリのルートディレクトリを定義
error_page ステータスコードに応じて表示するページを指定
upstream アプリケーションサーバーの指定
client_max_body_size 送られてくるファイル容量の上限を設定
gzip_static 圧縮したファイルを使うかを定義
try_files ファイルが存在するかを確認
proxy_set_header アプリケーションサーバーに送信するヘッダを定義
proxy_pass プロキシサーバーの指定

nginx.conf内にinclude /etc/nginx/conf.d/*.conf;という記述があるので、設定ファイルはetc/nginx/conf.dディレクトリ内に今回はrails.confというファイル名で作成します。

/etc/nginx/nginx.conf | nginx.confの中身 -->
1
2
3
4
5
6
# 略
  # Load modular configuration files from the /etc/nginx/conf.d directory.
  # See http://nginx.org/en/docs/ngx_core_module.html#include
  # for more information.
include /etc/nginx/conf.d/*.conf;
# 略

それでは下記のコマンドを実行して設定ファイルの作成と編集をしていきます。

EC2ターミナル | 設定ファイルの作成・編集
1
[ec2-user@ip-172-31-47-9 ~]$ sudo vi /etc/nginx/conf.d/rails.conf

ファイルが作成され、編集モードになるので、iを押してINSERTモードにし下記のコードを入力します。
※コードの内容は一例です。これでなくてはいけないというものではありません。

クローンするリポジトリ名ご自身のElastic IPアドレスの部分だけ差し替えてください。(全部で3箇所)

(例)
server unix:/var/www/pikawaka/tmp/sockets/unicorn.sock;
server_name 54.123.456.789;
root /var/www/pikawaka/public;

rails.conf | rails.confの編集 -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
upstream unicorn {
server unix:/var/www/クローンするリポジトリ名/tmp/sockets/unicorn.sock;
} server { listen 80;
server_name ご自身のElastic IPアドレス;
root /var/www/クローンするリポジトリ名/public;
location ^~ /assets/ { gzip_static on; expires max; add_header Cache-Control public; } 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://unicorn; } try_files $uri/index.html $uri @unicorn; error_page 500 502 503 504 /500.html; }

編集が完了したらescキーでINSERTモードから抜け、:wqと入力し編集モードから抜けましょう。

Unicornの設定をしよう

次はアプリケーションサーバーの設定を行なっていきます。
アプリケーションサーバーとはRailsで作成した動的コンテンツを動かすために必要なサーバーです。

アプリケーションサーバーは色々な種類があります。
例えばRails6でrails sコマンドを実行すると下記のようなログを確認できます。

ターミナル | rails sコマンドの実行
1
2
3
4
5
$ rails s
=> Booting Puma
=> Rails 6.0.0 application starting in development => Run `rails server --help` for more startup options Puma starting in single mode...

Booting Pumaと出力されているのはRailsアプリを動かすためにPumaを立ち上げたということを表しています。
PumaはRails6でデフォルトで使われているアプリケーションサーバーです。

EC2インスタンスでもアプリケーションサーバーを用意する必要があります。
今回はUnicornというアプリケーションサーバーを使ってデプロイする方法を解説していきます。

Unicornをインストールしよう

まずは公開するアプリにUnicornをインストールします。
これからのローカルの処理はmasterブランチで行なってください。

Gemfileのproduction環境にUnicornのgemを追記します。

Gemfile | Unicornの追加
1
2
3
group :production do
  gem 'unicorn', '5.4.1'
end

そしてbundle installコマンドでインストールをします。

ローカルのターミナル | gemのインストール
1
% bundle install

設定ファイルを作成しよう

次にconfigフォルダにunicorn.rbという設定ファイルを作成し、編集していきます。
下記のコマンドで設定ファイルを作成しましょう。
ローカルに作成するのでローカルのターミナルで実行します。

ローカルのターミナル | unicorn.rbファイルの作成
1
% touch config/unicorn.rb

次に作成したunicorn.rbを下記のように編集します。
※コードの内容は一例です。これでなくてはいけないというものではありません。

config/unicorn.rb | 設定ファイルの編集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# rootパスのディレクトリを指定
root_path = File.expand_path('../../', __FILE__)

# アプリケーションサーバの性能を決定する
worker_processes 2

# アプリケーションの設置されているディレクトリを指定
working_directory root_path

# プロセスIDの保存先を指定
pid "#{root_path}/tmp/pids/unicorn.pid"

# ポート番号を指定
listen "#{root_path}/tmp/sockets/unicorn.sock"

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

# 通常のログを記録するファイルを指定
stdout_path "#{root_path}/log/unicorn.stdout.log"

#応答時間を待つ上限時間を設定
timeout 30

# ダウンタイムなしでUnicornを再起動時する
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

記入ができたらcommitし、masterにpushしましょう。

デプロイするアプリをクローンしよう

次に先ほど作成したアプリケーションを保存するディレクトリに移動し、GitHubからデプロイするアプリをクローンします。
その前にGitHubでデプロイするアプリのリポジトリURLを確認しておきます。

リポジトリURLの確認

EC2ターミナル | アプリのクローン
1
2
3
4
# アプリを保存するディレクトリに移動
[ec2-user@ip-172-31-47-9 ~]$ cd /var/www/
# アプリのクローン
[ec2-user@ip-172-31-47-9 www]$ git clone リポジトリのURL

エラーなくクローンができればOKです。

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

次にクローンしたアプリのgemをEC2インスタンス内にインストールしていきます。
まずはbundlerをインストールしましょう。

bundlerはローカルにインストールされているバージョンと同じバージョンをインストールします。
下記のコマンドでローカルのbundlerのバージョンを確認します。

ローカルのターミナル | bundlerのバージョン確認
1
2
3
% bundler -v
# バージョンが表示(人によって異なります)
Bundler version 2.1.4

次に確認したバージョンと同じバージョンをEC2インスタンスにインストールします。
下記のコマンドをEC2ターミナルで実行します。

EC2ターミナル | bundlerのインストール
1
2
3
4
# アプリのディレクトリに移動
[ec2-user@ip-172-31-47-9 www]$ cd レポジトリ名
# バージョンはローカルのバージョンを指定
[ec2-user@ip-172-31-47-9 レポジトリ名]$ gem install bundler -v 2.1.4

次にgemをインストールしましょう。

EC2ターミナル | gemのインストール
1
[ec2-user@ip-172-31-47-9 レポジトリ名]$ bundle install

gemのバージョンが原因でインストールできないgemがあるときはローカルでgemをupdateしましょう。
その後、commit、pushし、EC2内でpullをしましょう。

ターミナル | gemのアップデート
1
2
3
4
5
6
7
8
# ローカルのターミナル
% bundle update gem名
% git add .
% git commit -m "gemのupdate"
% git push origin master
# EC2ターミナル
[ec2-user@ip-172-31-47-9 レポジトリ名]$ git pull origin master
[ec2-user@ip-172-31-47-9 レポジトリ名]$ bundle install

スワップファイルでメモリを強化

無料で使っているEC2インスタンスのメモリ不足でgemをインストールする際にエラーが発生することがあります。
そんな時、EC2ではスワップ領域を広げることでメモリを強化できます。
そのために必要なのがスワップファイルです

現在のスワップ領域を確認してみましょう。

EC2ターミナル | スワップ領域の確認
1
2
3
4
[ec2-user@ip-172-31-47-9 ~]$ grep Swap /proc/meminfo
SwapCached:            0 kB
SwapTotal:             0 kB
SwapFree:              0 kB

このように最初は0kBとなっています。
これからスワップファイルを使って、スワップ領域を広げていきます。
インスタンスの使用可能なメモリより小さくする必要があるので、今回は512MiBのスワップファイルを作成します。
デフォルトだとスワップファイルは用意されていないので、下記のコマンドで作成し、設定をしていきます。

※参照:AWS公式

EC2ターミナル | スワップファイルの編集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# rootに移動
[ec2-user@ip-172-31-47-9 ~]$ cd ~
# 512MBのスワップファイルを作成
[ec2-user@ip-172-31-47-9 ~]$ sudo dd if=/dev/zero of=/swapfile bs=1M count=512
# スワップファイルの読み書きのアクセス許可
[ec2-user@ip-172-31-47-9 ~]$ sudo chmod 600 /swapfile
# Linuxスワップ領域のセットアップ
[ec2-user@ip-172-31-47-9 ~]$ sudo mkswap /swapfile
スワップ空間バージョン 1 を設定します。サイズ = 512 MiB (536866816 バイト)
ラベルはありません, UUID=23c3156a-72b7-450f-955e-dcd08a5c79f6
# スワップ領域にスワップファイルを追加
[ec2-user@ip-172-31-47-9 ~]$ sudo swapon /swapfile
# 正常に完了したことを確認
[ec2-user@ip-172-31-47-9 ~]$ sudo swapon -s
ファイル名             タイプ       サイズ   使用済み    優先順位
/swapfile                               file        524284  0   -2

次に/etc/fstabファイルを編集して、起動時にスワップファイルを有効にします。

EC2ターミナル | スワップファイルの編集
1
[ec2-user@ip-172-31-47-9 ~]$ sudo vi /etc/fstab

ファイルが開くのでiを押してINSERTモードにします。
ファイルの末尾に新しい行を追加して下記のコードを追記します。

/etc/fstab | fstabファイルの編集
1
2
3
#
UUID=7b355c6b-f82b-4810-94b9-4f3af651f629     /           xfs    defaults,noatime  1   1
/swapfile swap swap defaults 0 0

その後、escキーを押してINSERTモードから抜け、:wqを入力して編集モードから抜けましょう。

ではスワップ領域が広がったか、確認してみましょう。

EC2ターミナル | スワップ領域の確認
1
2
3
4
[ec2-user@ip-172-31-47-9 ~]$ grep Swap /proc/meminfo
SwapCached:            0 kB
SwapTotal:        524284 kB
SwapFree:         524284 kB

このように広がっているのが確認できました。
確認ができたらgemをインストールできるかどうか試してみてください。

環境変数の定義をしよう

Railsアプリを動かすにはsecret_key_baseの情報が必要です。
これは外部に漏らしたくない情報なので環境変数で定義します。

環境変数の定義の仕方はdotenv-railsというgemを使う方法などいろいろありますが、今回は.bash_profile.zshrcファイルに定義している場合で解説していきます。

まずはアプリケーションディレクトリ上で下記のコマンドを実行しsecret_key_baseを作成します。

EC2ターミナル | secret_key_baseの作成
1
2
3
[ec2-user@ip-172-31-47-9 リポジトリ名]$ rake secret
# 下のような文字列が出力
066ebc882b8d80eb87381355b4b4ad2e9e73a83d969cb661e48b0c85f544c51ce63b9f7b64f471305b9af0926f65701b88614a1029bea7f75f6f7f6a2f93233d

こちらの値をコピーしておきましょう、

EC2インスタンス内の環境変数は/etc/environmentというファイルで管理します。
下記のコマンドで/etc/environmentファイルの編集を行います。

EC2ターミナル | `/etc/environment`の編集
1
[ec2-user@ip-172-31-47-9 レポジトリ名]$ sudo vi /etc/environment

するとファイルが開くのでiキーを押してINSERTモードにし、下記のコードを入力しましょう。

EC2ターミナル | `/etc/environment`の編集
1
2
DATABASE_PASSWORD='MariaDBのrootユーザーのパスワード'
SECRET_KEY_BASE='コピーしたsecret_key_baseの値'

その後、escキーでINSERTモードから抜け、:wqと入力し編集モードから抜けます。

データベースに接続するためのパスワードとsecret_key_baseの値を定義しました。
他にもデプロイするアプリで使っている環境変数も定義しておきましょう。

編集をしたら定義した環境変数を反映させるため、一度EC2インスタンスからログアウトします。
その後、再度ログインをしてenvコマンドを実行し、環境変数を呼び出せるか確認をしましょう。

ターミナル | 環境変数の確認
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# EC2インスタンスからログアウト
[ec2-user@ip-172-31-47-9 レポジトリ名]$ exit
ログアウト
# ローカルのターミナルから再度ログイン
% ssh 接続先名
# ログイン完了

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
# データベースのパスワードを表示させる
[ec2-user@ip-172-31-47-9 ~]$ env | grep DATABASE_PASSWORD
# データベースのパスワードが表示
DATABASE_PASSWORD=test
# secret_key_baseの値を表示させる
[ec2-user@ip-172-31-47-9 ~]$ env | grep SECRET_KEY_BASE
# secret_key_baseの値が表示
SECRET_KEY_BASE=066ebc882b8d80eb87381355b4b4ad2e9e73a83d969cb661e48b0c85f544c51ce63b9f7b64f471305b9af0926f65701b88614a1029bea7f75f6f7f6a2f93233d

ブラウザで確認してみよう

それではデプロイしたアプリをブラウザで確認してみましょう。

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

まずはcssやJavaScript、画像ファイルのコンパイルを行います。
ローカル環境ではこの作業は不要でしたが、本番環境では処理速度の関係で自動的に行われないので随時行う必要があります。
下記のコマンドでアセットファイルをコンパイルします。

EC2ターミナル | アセットファイルのコンパイル
1
2
3
4
# クローンしたアプリのディレクトリに移動
[ec2-user@ip-172-31-47-9 ~]$ cd /var/www/レポジトリ名
# アセットファイルのコンパイルを実行
[ec2-user@ip-172-31-47-9 レポジトリ名]$ rails assets:precompile RAILS_ENV=production

コンパイルが無事終了すればOKです。

エラーが出た場合

下記のようなエラーが出たらmaster.keyの値がセットされていません。

EC2ターミナル | エラーメッセージ
1
2
[ec2-user@ip-172-31-47-9 レポジトリ名]$ rails assets:precompile RAILS_ENV=production
Missing encryption key to decrypt file with. Ask your team for your master key and write it to /var/www/fuapp/config/master.key or put it in the ENV['RAILS_MASTER_KEY'].

先ほど環境変数を定義するところでRAILS_MASTER_KEYの値もセットしておきましょう。
セットする値はconfig/master.keyファイルの中身です。

EC2ターミナル | 環境変数の設定
1
2
3
[ec2-user@ip-172-31-47-9 レポジトリ名]$ sudo vi /etc/environment
# 編集モードで以下を追記
RAILS_MASTER_KEY="master.keyの中身"

その後、環境変数を適用させるため一度インスタンスから抜けて再度接続しなおしましょう。

database.ymlを編集しよう

本番環境でもデータベースを作成する必要があるので、ローカルのconfig/database.ymlの本番環境の定義部分を下記のように編集します。
databaseの値は編集しないでください。

config/database.yml | 本番環境の編集
1
2
3
4
5
6
production:
  <<: *default
  database: アプリ名_production
username: root
password: <%= ENV['DATABASE_PASSWORD'] %>
socket: /var/lib/mysql/mysql.sock

ローカルのファイルを編集したのでcommitし、pushします。
そしてEC2インスタンスでpullをしましょう。

データベースを作成しよう

これでデータベースサーバーに接続することができるようになりました。
次にEC2インスタンス内に今回のアプリで使用するデータベースを作成します。
下記のコマンドを実行します。

EC2ターミナル | データベースの作成
1
2
3
[ec2-user@ip-172-31-47-9 レポジトリ名]$ rails db:create RAILS_ENV=production
# 以下のように表示されればOK
Created database 'アプリ名_production'

次にデータベースにテーブルを作成します。

EC2ターミナル | テーブルの作成
1
[ec2-user@ip-172-31-47-9 レポジトリ名]$ rails db:migrate RAILS_ENV=production

エラーなくテーブルが作成されればOKです。

Railsを起動させよう

それではいよいよEC2インスタンス内でRailsを起動させます。

その前に一度Nginxを再起動させましょう。

EC2ターミナル | Nginxの再起動
1
2
[ec2-user@ip-172-31-47-9 レポジトリ名]$ sudo systemctl reload nginx
[ec2-user@ip-172-31-47-9 レポジトリ名]$ sudo systemctl start nginx

ローカルではrails sコマンドで起動させましたが、unicornを使った場合は下記のコマンドで起動します。

EC2ターミナル | Railsの起動
1
[ec2-user@ip-172-31-47-9 レポジトリ名]$ unicorn_rails -c config/unicorn.rb -E production -D

アプリが表示されるかどうか、Elastic IPアドレスでアクセスしてみましょう。
無事デプロイしたアプリが動けばデプロイ完了です!

エラーが発生してUnicornを起動できないとき

master failed to start, check stderr log for detailsのようなエラーメッセージが出てUnicornを起動できないときにはログを確認してみましょう。

エラーメッセージのログはUnicornの設定をした際に設定をいたしました。

config/unicorn.rb | 設定ファイルの編集
1
2
3
4
5
# エラーのログを記録するファイルを指定
stderr_path "#{root_path}/log/unicorn.stderr.log"
# 通常のログを記録するファイルを指定 stdout_path "#{root_path}/log/unicorn.stdout.log"

このファイルを確認すればエラーメッセージが確認できるので、修正すべき点を知ることができます。

EC2ターミナル | エラーメッセージの確認
1
2
3
# unicornのプロセスIDの確認
[ec2-user@ip-172-31-47-9 レポジトリ名]$ less log/unicorn.stderr.log
# エラーメッセージが表示

デプロイ後

デプロイ後、アプリのコードに変更をし、再度デプロイして変更点を反映させるにはRailsの再起動を行う必要があります。
再起動をするにはunicornのプロセスをkillし、再度立ち上げをします。
ローカルでのようにcontrolキー + cではシャットダウンできないので注意しましょう。

EC2ターミナル | Railsの再起動
1
2
3
4
5
6
# unicornのプロセスIDの確認
[ec2-user@ip-172-31-47-9 レポジトリ名]$ ps aux | grep unicorn
# 情報が表示される
ec2-user  1426  1.3 10.3 542944 104288 ?       Sl    5月28   0:01 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user  1435  0.0 10.2 544364 103192 ?       S     5月28   0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user  1622  0.0  0.0 119436   868 pts/0    S+   00:00   0:00 grep --color=auto unicorn

こちらの左から2番目のunicorn_rails masterのプロセスIDをkillしましょう。
unicorn_rails worker[0]も同時にkillされます。
プロセスIDはその時によって変化します。

EC2ターミナル | プロセスIDのkill
1
2
3
[ec2-user@ip-172-31-47-9 レポジトリ名]$ kill 1426
# 起動コマンドの実行
[ec2-user@ip-172-31-47-9 レポジトリ名]$ unicorn_rails -c config/unicorn.rb -E production -D

cssやJavaScriptなどのアセットファイルを変更した場合はコンパイルするコマンドを実行するのも忘れないようにしましょう。

インスタンスを停止をしよう

一度インスタンスを起動すると起動時間に応じて料金が発生します。
※参照:EC2の料金表

無料期間中は一ヶ月750時間までは無料です。
インスタンスを2つ作成し、どちらも稼働している場合は両方の合計になるので一ヶ月稼働しっぱなしの場合は料金が発生します。

インスタンス停止中は料金が発生しないので、使わないときは停止しておきましょう。
※ただしElastic IPアドレスが紐づいているとElastic IPアドレスの料金が発生するので、この後解説する方法でElastic IPアドレスを解放する必要があります

インスタンスの一覧画面から停止したいインスタンスのチェックボックスにチェックを入れて、「インスタンスの停止」を選択し、クリックします。

インスタンスの停止

確認画面になるので「停止」をクリックします。

確認画面

するとインスタンスが停止され、デプロイしたアプリにアクセスしても表示がされなくなります。

再び起動させたい場合は先ほどの選択肢から「インスタンスを開始」を選びます。
保留中になりますが数分経つと再びインスタンスが起動します。

その後は再度ssh接続でインスタンスに接続し、MariaDB、Nginx、Unicornを起動するコマンドを打ち、Railsを立ち上げましょう。

EC2ターミナル | それぞれの起動コマンドを実行
1
2
3
4
[ec2-user@ip-172-31-47-9 ~]$ cd /var/www/レポジトリ名
[ec2-user@ip-172-31-47-9 レポジトリ名]$ sudo systemctl start mariadb
[ec2-user@ip-172-31-47-9 レポジトリ名]$ sudo systemctl start nginx
[ec2-user@ip-172-31-47-9 レポジトリ名]$ unicorn_rails -c config/unicorn.rb -E production -D

ただしElastic IPアドレスに関連づけられているインスタンスを停止してしまうとElastic IPアドレスの利用料金が発生してしまうので、この後に解説する方法でElastic IPアドレスも解放(削除)しておきましょう。

インスタンスを削除しよう

不要になったインスタンスは削除してしまいましょう。
ただし、削除すると二度と元に戻せなくなるので注意が必要です。

停止するとき同様に選択肢から「インスタンスを終了」を選択してクリックします。

インスタンスの削除

同じように確認画面になるので「終了」をクリックしましょう。

確認画面

一覧画面を見ると「終了済み」となっているのが確認できます。

インスタンス一覧

数時間経つと終了済みのインスタンスは一覧画面から消えます。

Elastic IPアドレスを削除しよう

Elastic IPアドレスが実行中のインスタンスに関連づけられていない場合や停止しているインスタンスに関連づけられている場合は料金が発生してしまうので、関連付けたElastic IPアドレスも削除しましょう。
Elastic IPの一覧から「アクション」をクリックし、「Elastic IPアドレスの解放」をクリックします。

Elastic IPアドレスの解放

確認画面になるので「解放」をクリックしましょう。

確認画面

料金を確認しよう

ここまで無料でEC2インスタンスにアプリをデプロイするまでの流れを解説してきました。
ですが、インスタンスを停止したり、削除した後もElastic IPアドレスを解放していないと料金が発生してしまいます。
無料で使いたい方は「マイ請求ダッシュボード」で料金をこまめに確認しておきましょう。

マイ請求ダッシュボード

このように発生している料金や、無料枠がどれだけ使われているか確認することができます。

料金の確認

もし料金が発生してしまっている場合は慌てずに対応しましょう。
確認画面の「料金明細」をクリックするとより詳しい内容が確認できます。

料金明細

「すべて展開」をクリックしましょう。

すべて展開

このように具体的にどのサービスで料金が発生しているか確認できます。
この場合だとElastic IPアドレスの使用量が発生しているということがわかりました。
紐づけているインスタンスを停止していたためだと原因を突き止めることができました。

料金の確認

身に覚えがない大量の料金が発生している場合はアカウントが不正に使われている可能性もあります。
その際は速やかにAWSに連絡を取るのが良いでしょう。

AWSはとても便利なサービスですので、上記のことに気をつけながら運営をしていきましょう。

この記事のまとめ

  • EC2を使ってインスタンス(仮想サーバー)を作成
  • webサーバーとアプリケーションサーバーを用意する必要がある
  • GitHubと連携をしてアプリをクローンする