LoginSignup
13
18

More than 3 years have passed since last update.

Rails5.2以降でAWSへデプロイ完全版+DBはmysql+無料でSSL化+独自ドメイン取得(お名前.com)

Last updated at Posted at 2020-04-07

はじめに

表題の通りですがAWSにて環境構築から独自ドメイン取得までを記載しております。
rails5.2以降でのデプロイが難航し環境構築から独自ドメイン取得まで一貫した記事が無く、人柱となりて共有できればと思い記事として残すことにしました。
rails5.2以降ではsecrets.ymlがcredentials.yml.encに変更になり、呼び出し方が異なるのでその部分が躓くかと存じます。また、ドメイン・SSL化はなかなか教材には無かったのでご参考になれば幸いです。不手際がございましたら、コメントにいただけると有り難いです。
できるだけコピペでいきたいですね。では参りましょう!

前提条件

  1. githubにリポジトリが登録できている
  2. そのリポジトリに rails new したもの(rails5.2以降)が登録できている
  3. databaseはmysqlである
  4. AWSでアカウントが登録できている
  5. 寛大な心を持っている

流れ

  1. AWS内の環境構築
  2. unicornの導入
  3. nginxの導入
  4. capistranoの導入
  5. お名前.comでドメインを購入し、AWSと紐付け
  6. 無料SSL化(Let's Encrypt)

AWS内の環境構築

AWSのEC2というサービスを使って、全世界に作成したサイトを公開するサーバを作成します。いくつかの設定をし、作成したサーバにログインして操作できるようにします。EC2で作成したサーバは、結局はターミナルを介して遠隔操作できるパソコンです。慣れましょう!(投げやり感)

  • AWSアカウントのリージョン設定

リージョンとは、AWSの物理的なサーバの場所を指定するものです。リージョンは世界各地に10箇所以上存在し、そのうちの一つは東京にあります。
まずは【こちら】からAWSアカウントにログインします。次に日本にお住まいの方は「東京」を選択してください。
51832aef26a6cc6d565fe8bf6019afba.png

  • EC2インスタンスの作成

「仮想マシン」のことをAWSでは「EC2インスタンス」と呼んでいます。
「EC2」を選択しましょう。
スクリーンショット 2020-04-07 12.25.01.png

以下の画像のように「インスタンスの作成」をクリックしましょう。
10ad61a4bbb8c5884c949a10949503d4.png

以下の画像のように「 Amazon Linux AMI 」を選択してください。
1c8f643be5a1508198df274a862d6f6b.png

EC2インスタンスのタイプを選択します。EC2ではさまざまなインスタンスタイプが用意されており、CPUやメモリなどのスペックを柔軟に指定することができます。
今回は、無料枠で利用できる「t2.micro」を選択しましょう。
905d450ae5744b85123dfedbed1295a1.png

起動をクリックします。
fbe1198a6088977bc8c1039bedeba292.png

6c95b174278c701dbd137eb03f62aaa4.png

「キーペア」をダウンロードすることが出来ます。こちらはインスタンスにSSHでログインする際に必要となる「秘密鍵」です。これがないとEC2インスタンスにログインできないので、必ずダウンロードしてパソコンに保存しておきましょう。
※スペースを含まない名前の秘密鍵を作成するようにしましょう!

キーペアのダウンロードが完了すると、クリック出来ない状態になっていた「インスタンスの作成」が、クリックできるように変更されます。そちらをクリックして、EC2インスタンスを作成しましょう。
その後、インスタンス一覧画面に戻り、作成した「インスタンスID」をコピーしてメモしておきましょう。
b1294ea2334ac077df3066fb6efc1bb1.png

  • Elastic IPの作成と紐付け

Elastic IPとは、AWSから割り振られた固定のパブリックIPアドレスのことです。
Elastic IPを取得するために、以下の画像の手順に従って作業をしていきましょう。
4606e905b17c4ebc204e6bd9878fd1c6.png

Amazonプールを選択して次へ。
3a79240f4cbe77eddba4983dda230db6.png

daa2e2eb2ba3fd2a42c661f45a0aba0c.png

0b53abdd98d051b4fb7545ec0fba2774.png

f82dfa7630fc13796a721341008e6b4b.png

b570057964f8ae1119bff0b7e63e7f2f.png

上の画像のようにインスタンスを選択すると、その下にあるプライベートIPアドレスが自動で選択されます。

再びインスタンス一覧画面に戻り、作成したインスタンスの「パブリック IP」と「Elastic IP」が同じものに設定されていることを確認しましょう。

5210f7004f6c8bb620cc794775bd0832.png

  • ポート解放1

立ち上げたばかりのEC2インスタンスはSSHでアクセスすることはできますが、HTTPなどの他の接続は一切つながらないようになっています。そのため、WEBサーバとして利用するEC2インスタンスは事前にHTTPがつながるように「ポート」を開放する必要があります。
「セキュリティグループ」のリンクlaunch-wizard-1をクリックします。
7ee866ffd3f4791fc04ec4e7f820a260.png

「インバウンド」タブの中の「編集」をクリックします。
5668fc324ef4003048568c7ca675d2a0.png

「ルールの追加」をクリックします。
タイプを「HTTP」、プロトコルを「TCP」、ポート範囲を「80」、送信元を「カスタム / 0.0.0.0/0, ::/0」に設定します。「0.0.0.0」や「::/0」は「全てのアクセスを許可する」という意味です。

  • EC2インスタンスへのログイン

EC2インスタンスを作成すると、ec2-userというユーザーと対応するSSH秘密鍵が生成されました。
ターミナルで以下のコマンドを実行しましょう。

ターミナル(ローカル)
$ cd ~

$ mkdir ~/.ssh
# .sshというディレクトリを作成
# File existsとエラーが表示されたとしても、.sshディレクトリは存在しているということなので、そのまま進みましょう。

$ mv Downloads/ダウンロードした鍵の名前.pem .ssh/
# mvコマンドで、ダウンロードしたpemファイルを、ダウンロードディレクトリから、.sshディレクトリに移動します。

$ cd .ssh/

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

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

$ ssh -i ダウンロードした鍵の名前.pem ec2-user@作成したEC2インスタンスと紐付けたElastic IP
#(例えばElastic IPが123.456.789であれば、shh -i ダウンロードした鍵の名前.pem ec2-user@123.456.789 というコマンドになります)
#(ダウンロードした鍵を用いて、ec2-userとしてログイン)

Elastic IP は各自のAWSアカウントから確認してください。
以下の様なメッセージが表示されることがありますが、「yes」と入力して下さい。

ターミナル(ローカル)
$ ssh -i aws_key.pem ec2-user@52.68.~~~~~~
The authenticity of host '52.68.~~~~~~ (52.68.~~~~~~)' can't be established.
RSA key fingerprint is eb:7a:bd:e6:aa:da:~~~~~~~~~~~~~~~~~~~~~~~~.
Are you sure you want to continue connecting (yes/no)? 

ターミナルのコマンド待ちの際の左側の表示が、以下の画像のように
[ec2-user| ...

となればログイン成功です!
7007fc748bb3eed885226a56dd63d2e4.png

以上で、AWSの設定とEC2インスタンスの生成が完了でございます。

  • 必要なツールのインストール

ターミナルで以下のコマンドを実行しパッケージをアップデートしましょう。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y update

次に、その他環境構築に必要なパッケージを諸々インストールします。

ターミナル(EC2サーバー)
[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 libcurl libcurl-devel curl

ちなみに-y はyumコマンドのオプションで全ての問いにYesで自動的に答えるという意味だぞ❤️

  • Node.jsをインストール

サーバーサイドで動くJavaScriptのパッケージです。今後のデプロイに向けた作業の中で、CSSや画像を圧縮する際に活用されます。ターミナルでNode.jsをインストールしましょう。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo curl -sL https://rpm.nodesource.com/setup_6.x | sudo bash -
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install nodejs
  • rbenvとruby-buildをインストール

ターミナルでrbenvとruby-buildをインストールしましょう。

ターミナル(EC2サーバー)
#rbenvのインストール
[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 
#rbenvを呼び出すための記述
[ec2-user@ip-172-31-25-189 ~]$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
#.bash_profileの読み込み
[ec2-user@ip-172-31-25-189 ~]$ source .bash_profile
#ruby-buildのインストール
[ec2-user@ip-172-31-25-189 ~]$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
#rehashを行う
[ec2-user@ip-172-31-25-189 ~]$ rbenv rehash
  • Rubyをインストール

自身のアプリケーションで使っているRubyのバージョンによって適宜変更してください。
ここでは、2.5.1をインストールしていきます。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ rbenv install 2.5.1
[ec2-user@ip-172-31-25-189 ~]$ rbenv global 2.5.1
[ec2-user@ip-172-31-25-189 ~]$ rbenv rehash  #rehashを行う
[ec2-user@ip-172-31-25-189 ~]$ ruby -v # バージョンを確認
  • MySQLをインストール

Amazon Linuxを利用している場合、MySQLは yum コマンドからインストールすることができます。
以下のコマンドを実行してください。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install mysql56-server mysql56-devel mysql56

これは、MySQLのバージョン5.6をインストールすることを意味します。

  • MySQLを起動しよう
ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo service mysqld start

mysql ではなく mysqld であることに注意しましょう。「d」はLinuxの用語で「サーバ」を意味する「デーモン(daemon)」の頭文字です。
起動できたか確認するために、以下のコマンドを打ってみましょう。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo service mysqld status
mysqld (pid  15692) is running...

「running」と表示されれば、MySQLの起動は成功です。

  • MySQLのrootパスワードの設定

以下のコマンドでパスワードを設定しましょう。'設定したいパスワード'の部分については、例えばpassword0000という文字列を設定するとしたら、 'password0000'と記載しましょう。
※0から始まるpasswordは読み込んでくれないケースが多いので、避けましょう!

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo /usr/libexec/mysql56/mysqladmin -u root password 'ここを設定したいパスワードに変更してからコマンドを実行してください'

このパスワードは、後ほどRailsからアクセスする時にも利用するので記憶しておいてください。
この時、Warning: Using a password on the command line interface can be insecure.
と警告がでることがありますが、ここでは無視していただいて問題ありません。

設定したパスワードが使えるか確認してみましょう。以下のコマンドを入力してください。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ mysql -u root -p

Enter password: とパスワードを入力するように表示されるので、先程設定したパスワードを入力して、Enterしてください。以下のように表示されれば、MySQLの設定は終了です。

ターミナル(EC2サーバー)
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.6.33 MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

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

mysql>

以上で、各ツールのインストールが完了でございます。

  • EC2のサーバにGithubのコードをクローン

現状、EC2サーバにアプリケーションのコードをクローンしようとしてもpermission deniedとエラーが出てしまいます。
これは、Githubから見てこのEC2インスタンスが何者かわからないためです。
以下のコマンド入力して、EC2サーバのSSH鍵ペアを作成しましょう。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 ~]$ 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公開鍵を表示し、値をコピーします。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 ~]$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2E......

そして、catで表示させた公開鍵を、Githubにアクセスして登録していきます。
まず、以下のURLにアクセスしてください。
https://github.com/settings/keys
fb528668062ce467f263dc9f66940acc.jpeg

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

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

途中でこのまま続けるかどうかYes/Noで聞かれることがありますが、Yesで進んでください。
Permission denied (publickey).
と表示された場合は、SSH鍵の設定が間違っているので、作業を確認してください。

unicornの導入

unicornは rails s の代わりを担ってくれるアプリケーションサーバです。(アバウトすぎw)

  • Unicornをインストール

次のように ローカルでGemfile を編集しましょう。

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

ローカルのrails newしたディレクトリでbundle installコマンドを実行してください。

ターミナル(ローカル)
$ bundle install

config/unicorn.rbを作成し、内容を以下のように編集して保存しましょう。

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
  • デプロイ時のエラー対策

Uglifierというgemがあり、これはJavaScriptを軽量化するためのものです。しかし、ChatSpaceのJavaScriptで使用しているテンプレートリテラル記法(`)に対応していません。そのため、デプロイ時にエラーの原因となります。
デプロイ時にエラーの原因となる記述の対策として、下記のフォルダを編集しましょう。

config/environments/production.rb(修正前)
config.assets.js_compressor = :uglifier
config/environments/production.rb(修正後)
# config.assets.js_compressor = :uglifier
  • 変更修正をリモートリポジトリに反映

ここまで、ローカルのフォルダ内で変更修正を行ったので、GitHub Desktopからコミットしてプッシュしましょう。この時必ず、masterブランチで行うようにしてください。もし、別ブランチでコミット&プッシュした場合は、リモートリポジトリでプルリクエストを作成し、ブランチをmasterへマージしてください。

  • Githubからコードをクローン

続いて、Unicornの設定を済ませたコードをEC2インスタンスにクローンしましょう。
まず、以下のコマンドを入力して、ディレクトリを作成します。今回は、ここで作成したディレクトリにアプリケーションを設置することにします。

ターミナル(EC2サーバー)
#mkdirコマンドで新たにディレクトリを作成
[ec2-user@ip-172-31-23-189 ~]$ sudo mkdir /var/www/
#作成したwwwディレクトリの権限をec2-userに変更
[ec2-user@ip-172-31-23-189 ~]$ sudo chown ec2-user /var/www/

Githubから「リポジトリURL」を取得します。
e5163d180a6607ede9bcc85bd035843c.png

取得した「リポジトリURL」を使って、コードをクローンします。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/
[ec2-user@ip-172-31-23-189 www]$ git clone https://github.com/<ユーザー名>/<リポジトリ名>.git
  • Swap領域を用意

コンピュータが処理を行う際、メモリと呼ばれる場所に処理内容が一時的に記録されます。メモリは容量が決まっており、容量を超えてしまうとエラーで処理が止まってしまいます。Swap領域は、メモリが使い切られそうになった時にメモリの容量を一時的に増やすために準備されるファイルです。

まずは、ホームディレクトリに移動します。

ターミナル(EC2サーバー)
#ホームディレクトリに移動
[ec2-user@ip-172-31-25-189 ~]$ cd

続いて、以下の順番でコマンドを実行します。

ターミナル(EC2サーバー)
#処理に時間がかかる可能性があるコマンドです
[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) コピーされました、 7.35077 秒、 73.0 MB/秒
ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo chmod 600 /swapfile1
ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo mkswap /swapfile1
# 以下のように表示されれば成功
スワップ空間バージョン1を設定します、サイズ = 524284 KiB
ラベルはありません, UUID=74a961ba-7a33-4c18-b1cd-9779bcda8ab1
ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo swapon /swapfile1
ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab'

※最後のコードは見づらくなっていますが、「/swapfile1 none」より右に続きがありますのでご注意ください。

これで、Swap領域を確保することができました。

  • クローンしたディレクトリに移動し、 rbenvでインストールされたRubyが使われているかチェック
ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 www]$ cd  /var/www/<リポジトリ名>
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ruby -v
ruby 2.5.1p112 (2016-04-26 revision 54768) [x86_64-linux]

ruby 2.5.1 ...となっていれば成功です。そうでない場合は、もともと用意されているRubyが利用されているので、Rubyのインストールが成功しているか確認してください。

  • bundlerをインストール

まず今まで開発環境(ローカル)で開発してきたアプリにおいて、どのバージョンのbundlerが使われていたのか確認します。

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

開発環境で仕様しているbundlerのバージョンがわかったので、同じバージョンのものをEC2サーバ側にも導入します。上記の場合では、bundler 2.0.1のバージョンを導入して bundle install を実行します。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ gem install bundler -v 2.0.1
# ローカルで確認したbundlerのバージョンを導入する
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle install
# 上記コマンドは、数分以上かかる場合もあります。
  • 環境変数の設定

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

  • secret_key_base

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

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rake secret
69619d9a75b78f2e1c87ec5e07541b42f23efeb6a54e97da3723de06fe74af29d5718adff77d2b04b2805d3a1e143fa61baacfbf4ca2c6fcc608cff8d5a28e8d

この長い英数の羅列は、この後利用するのでコピーしておきましょう。

  • 実際にEC2インスタンスに環境変数を設定

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

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 ~]$ sudo vim /etc/environment

iと打ち込んで入力モードに切り替えた後、下記の記述を打ち込みます。=の前後にスペースは入れません。

/etc/environment
#先程設定したMySQLのrootユーザーのパスワードを入力
DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'
SECRET_KEY_BASE='先程コピーしたsecret_key_base'

入力ができたら、escキーを押した後、:wqで保存しましょう。

  • 設定した環境変数を反映させるために、一度本番環境をログアウト
ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 ~]$ exit
logout
Connection to 52.xx.xx.xx closed.
  • もう一度本番環境へログイン
ターミナル(ローカル)
$ ssh -i [ダウンロードした鍵の名前].pem ec2-user@[作成したEC2インスタンスと紐付けたElastic IP]
(ダウンロードした鍵を用いて、ec2-userとしてログイン)
  • 設定した環境変数が本当に適用されているか確認
ターミナル(EC2サーバー)
[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ユーザーのパスワード'
  • ポート解放2

先程、 config/unicorn.rb に listen 3000を設定しました。そのため、WEBサーバとして利用するEC2インスタンスは事前にHTTPがつながるように「ポート」を開放する必要があります。
「セキュリティグループ」のリンクlaunch-wizard-1をクリックします。
7ee866ffd3f4791fc04ec4e7f820a260.png

「インバウンド」タブの中の「編集」をクリックします。
5668fc324ef4003048568c7ca675d2a0.png

「ルールの追加」をクリックします。
タイプを「カスタムTCPルール」、プロトコルを「TCP」、ポート範囲を「3000」、送信元を「カスタム」「0.0.0.0/0」に設定します。
e142ed6d793012c40b97f6e0a4d8e4df.png

以上で、ポートの開放が完了です。
この作業が終わっていないと、起動したRailsにアクセスできないので注意してください。

  • Railsを起動する

いよいよRailsの起動です。
以下のコマンドを実行し、ユニコーンを起動

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/[リポジトリ名]
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D

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

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D
master failed to start, check stderr log for details

なので、Unicornのエラーログを確認しましょう。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ less log/unicorn.stderr.log
I, [2016-12-21T04:01:19.135154 #18813]  INFO -- : Refreshing Gem list
I, [2016-12-21T04:01:20.732521 #18813]  INFO -- : listening on addr=0.0.0.0:3000 fd=10
E, [2016-12-21T04:01:20.734067 #18813] ERROR -- : Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/mysql2_adapter.rb:29:in `rescue in mysql2_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/mysql2_adapter.rb:12:in `mysql2_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:721:in `new_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:765:in `checkout_new_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:744:in `try_to_checkout_new_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:705:in `acquire_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:501:in `checkout'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:364:in `connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:875:in `retrieve_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_handling.rb:128:in `retrieve_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_handling.rb:91:in `connection'
config/unicorn.rb:36:in `block in reload'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/unicorn-5.1.0/lib/unicorn/http_server.rb:502:in `spawn_missing_workers'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/unicorn-5.1.0/lib/unicorn/http_server.rb:132:in `start'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/unicorn-5.1.0/bin/unicorn_rails:209:in `<top (required)>'
/home/ec2-user/.rbenv/versions/2.5.1/bin/unicorn_rails:23:in `load'
/home/ec2-user/.rbenv/versions/2.5.1/bin/unicorn_rails:23:in `<main>'

このERRORという行を見てみると、これは本番環境でインストールするmysqlの設定がローカルとは異なるため、mysqlへ接続できなくなっている状態です。

database.ymlの本番環境の設定を編集

config/database.yml(ローカル)
production:
  <<: *default
  database: <リポジトリ名>_production(それぞれのアプリケーション名によって異なっています。)
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

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

サーバ上のアプリケーションにも反映させたいので、以下のようにコマンドを実行してください。

ターミナル(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 '<データベース名>'
[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が起動していない可能性があります。sudo service mysqld startというコマンドをターミナルから打ち込み、mysqlの起動を試してみましょう。

再度Railsを起動。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D

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

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

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

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

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
...

すると、以下のようにプロセスが表示されるはずです。

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

killコマンドを入力してUnicornのプロセスを停止

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのPID>
...

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

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

下記の2行が表示が消えていない場合はプロセスが終了できていないことになります。

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

そのような場合は、プロセスを強制終了しましょう。オプション-9をkillコマンドにつけると強制終了を実行できます。通常のkillコマンドで削除できない場合はこちらを使用しましょう。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ kill -9 [プロセスID]  

#プロセスIDはpsコマンドで検索した結果の数字に置き換えてください。上記であれば17877です。

unicornを起動

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

nginxの導入

Nginx(エンジン・エックス)とは、Webサーバの一種です。

  • Nginxをインストール
ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install nginx
  • Nginxの設定ファイルを編集

vimコマンドを使ってターミナル上で編集していきます。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf
rails.conf
upstream app_server {
  # Unicornと連携させるための設定。アプリケーション名を自身のアプリ名に書き換えることに注意。今回であればおそらくchat-space
  server unix:/var/www/<アプリケーション名>/tmp/sockets/unicorn.sock;
}

# {}で囲った部分をブロックと呼ぶ。サーバの設定ができる
server {
  # このプログラムが接続を受け付けるポート番号
  listen 80;
  # 接続を受け付けるリクエストURL ここに書いていないURLではアクセスできない
  server_name <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点は書き換えが必須です。

3行目の<アプリケーション名> となっている箇所は、ご自身のものに変更してください。
11行目の<Elastic IP>となっている箇所も同様に、ご自身のものに変更してください。
14行目の<アプリケーション名> となっている箇所は、ご自身のものに変更してください。

※この場合<>は記入不要なもの/表示されないものとして捉えてください。説明のための日本語文字列を明示するために<>で囲んでいます。

  • nginxの権限を変更

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

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ cd /var/lib
[ec2-user@ip-172-31-25-189 lib]$ sudo chmod -R 775 nginx

これで、Nginxの設定が完了しました。

  • Nginxを再起動して設定ファイルを再読み込み
ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 lib]$ cd ~
[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx restart
  • ローカルでunicorn.rbを修正

次にNginxを介した処理を行うためにunicornの設定を修正します。

unicorn.rb(ローカル)
listen 3000

↓以下のように修正

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

ローカルで編集したファイルをリモートへpush

  • ローカルの変更点を本番環境へ反映
ターミナル(EC2サーバー)
# まず、chat-spaceのディレクトリに移動
[ec2-user@ip-172-31-25-189 ~]$ cd /var/www/chat-space
[ec2-user@ip-172-31-23-189 <レポジトリ名>]$ git pull origin master
  • Unicornを再起動

まず、プロセスの番号を確認します。

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

続いて、プロセスをkillします。

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

Unicornを起動します。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
...
  • ブラウザからElastic IPでアクセス

ブラウザからElastic IPでアクセスすると、アプリケーションにアクセスできます(:3000をつける必要はありません)。なお、この時もunicornが起動している必要があります。

capistranoの導入

capistranoは、自動デプロイツールと呼ばれるものの一種です。自動デプロイツールを利用することによって、デプロイ時に必要なコマンド操作が1回で済むようになります。

  • capistranoを利用するためのGemをインストール
gemfile(ローカル)
group :development, :test do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
end

続いて、Gemfileを読み込みましょう。

ターミナル(ローカル)
bundle install

gemを読み込めたら、下記のコマンドを打ちます。

ターミナル(ローカル)
bundle exec cap install

すると、下記のようにファイルが生成されます。

アプリケーション名
📂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を下記のように編集
config/deploy/production.rb
server '<用意したElastic IP>', user: 'ec2-user', roles: %w{app db web}
  • 下記の指示に従い、deploy.rbを編集

deploy.rbの記述をすべて削除し、以下のコードを貼り付けます。

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

# Capistranoのログの表示に利用する
set :application, '<自身のアプリケーション名>'

# どのリポジトリからアプリを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, 2.5.1 #<このアプリで使用しているrubyのバージョン>

# credentials.yml.encではmasterkeyにする
set :linked_files, %w{config/master.key}

# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
                  keys: ['<ローカル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:stop'
    invoke 'unicorn:start'
  end
  desc 'upload master.key'
 task :upload do
   on roles(:app) do |host|
     if test "[ ! -d #{shared_path}/config ]"
       execute "mkdir -p #{shared_path}/config"
     end
     upload!('config/master.key', "#{shared_path}/config/master.key")
   end
 end
 before :starting, 'deploy:upload'
 after :finishing, 'deploy:cleanup'
end

以下の5点は書き換えが必須です。

  1. 3行目のはご自身のバージョンを記述しましょう。
  2. 6行目の<自身のアプリケーション名>はご自身のものを記述しましょう。
  3. 9行目の/<レポジトリ名>も同様に、ご自身のもの記述してください。
  4. 14行目の<このアプリで使用しているrubyのバージョン>はご自身のものを確認して記述してください。
  5. 21行目の<ローカルPCのEC2インスタンスのSSH鍵(pem)へのパス>も同様に、ご自身のもの記述してください。
  • 以下の指示にしたがって、unicorn.rbの記述を編集
config/unicorn.rb
#サーバ上でのアプリケーションコードが設置されているディレクトリを変数に入れておく
app_path = File.expand_path('../../../', __FILE__)

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

#アプリケーションの設置されているディレクトリを指定
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"

#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
  • 本番環境でのnginxの設定ファイルも変更
ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf

以下のように変更しましょう

rails.conf
upstream app_server {
  # sharedの中を参照するよう変更
  server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name <Elastic IPを記入>;

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

  # currentの中を参照するよう変更
  root /var/www/<アプリケーション名>/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    # currentの中を参照するよう変更
    root   /var/www/<アプリケーション名>/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;
}

もう一度記述すべき箇所が記述できているか確認しましょう。

  1. 3行目の<アプリケーション名> となっている箇所は、ご自身のものに変更してください。
  2. 11行目の<アプリケーション名>となっている箇所も同様に、ご自身のものに変更してください。
  3. 18行目の<アプリケーション名>となっている箇所も同様に、ご自身のものに変更してください。

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

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

自動デプロイを実行する前に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

続いて、プロセスをkillします。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのPID(上記では17877)>
...
  • ローカルのcredentials.yml.encを編集

ここで注意したいのが、本番環境のcredentials.yml.encを編集すると、master.keyが自動生成されてしまい、ローカル環境のmester.keyが一致しなくなり、起動できなくなるので注意が必要です。
もし、本番環境のcredentials.yml.encを編集してしまった場合は、一度master.keyとcredentials.yml.encをコマンドで消去し、ローカルのcredentials.yml.encをpullしましょう。

下記コマンドで暗号化されていない、credentials.yml.encを開くことができ、編集することができます。

ターミナル(ローカル)
$ EDITOR=vim bin/rails credentials:edit
credentials.yml.enc
# S3使用時
# aws:
#   access_key_id: 123
#   secret_access_key: 123

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: 先程コピーしたsecret_key_base

secret_key_baseは上記で作成したものを貼り付けましょう。
もし、忘れてしまった場合、本番環境での確認方法は下記の通りです。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 ~]$ env | grep SECRET_KEY_BASE
SECRET_KEY_BASE='secret_key_base'
  • 本番環境のshared/configにmaster.keyを作成

このままデプロイしても以下のようなエラーが出てしまいます。

ターミナル(ローカル)
ERROR linked file /var/www/techlog/shared/config/master.key does not exist on <Elastic IP>

エラー通り、本番環境のshared/configにmaster.keyを作ります。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 ~]$ touch /var/www/アプリケーション名/shared/config/master.key

作成したmaster.keyを編集します。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 ~]$ vim /var/www/アプリケーション名/shared/config/master.key

ローカルのmaster.keyの内容をコピーし、本番環境のmaster.keyにコピーします。

以上で編集作業完了です。

  • 最後に魔法の一文

ローカルで下記のコマンドを入力すると、自動デプロイを実行できます。

ターミナル(ローカル)
# アプリケーションのディレクトリで実行する
$ bundle exec cap production deploy

上記コマンドを実行し、以下の画像のようにエラーが表示されずに完了したら自動デプロイは完了です。
809540b10e599864031a58c3ce6cff07.png

もし、途中でエラーが出て止まってしまった場合は、以下を試します。

  1. そのままもう一度同じコマンドを実行してみる 特に、bundle installのタスクの際に、初めて自動デプロイを実行する場合は、メモリ不足で落ちることがあります
  2. 記述ミスが無いか 特に、本カリキュラムにおいて、修正したファイルに注目して確認しましょう
  3. 手順を飛ばしていないか bundle installなどのコマンド実行を忘れていないか確認しましょう
  • ブラウザからElastic IPでアクセス

ブラウザからElastic IPでアクセスすると、アプリケーションにアクセスできます(:3000をつける必要はありません)。正しく動いていることを確認しましょう。

確認できればデプロイは一旦完了です。長時間お疲れ様でした!

お名前.comでドメインを購入し、AWSと紐付け

大まかな流れです。

  1. お名前.comでドメインを購入
  2. route53にDNSの設定と、ElasticIPの登録
  3. お名前ドットコムにroute53の情報を登録

では参りましょう!

  • お名前.comでドメインを購入

お名前.comでアカウント登録と取得したいドメインを購入しましょう。
年単位での契約になります。

  • route53とは

AWSのDNSサービスで、AWS上の各サービスを独自ドメインで利用する上で便利な機能が用意されていて親和性が高いサービスになっています。

  • route53の設定!

route53にログイン

awsマネジメントコンソールのサービスから、Route 53を開きます。
aws_route53_00-1024x569.png

DNS管理のところにある「今すぐ始める」ボタンを押していきます。
aws_route53_01-1024x640.png

「ホストゾーンを作成」ボタンを押して、どのドメインに関するホストゾーンを作成するかを設定していきます。
「ドメイン名」のところには、お名前.comで取得したドメインを入力します。
aws_route53_03-1024x569.png

ホストゾーンを作成すると、NSレコードにネームサーバーが4つ割り当てられています。
このネームサーバーの情報はお名前.com側の設定で入力するので内容をメモしておきます。
aws_route53_04-1024x569.png

  • 作成したホストゾーンにEC2の固定IPアドレスを割り当てる

「レコードセットの作成」ボタンを押して、「名前」に対象のドメイン、値にEC2で割り当てられた固定IPアドレスを入力し「作成」ボタンを押せば完了です。
aws_route53_05-1024x569.png

  • お名前.comの設定でRoute 53に向けるネームサーバーの設定を行う

ドメインNaviでAWSで利用するドメインの設定を開き、ネームサーバーの変更から「他のネームサーバーを利用」を選択します。
ネームサーバー情報の入力欄に、Route 53のホストゾーンのNSレコードに表示されていたネームサーバーを4つとも入力し登録できれば設定は完了です。
aws_domain_navi_02-1024x640.png

これでお名前.comで取得したドメインにアクセスした際に、AWSのRoute 53で受けることができるようになりました。

  • ドメインの動作確認

最後に動作確認をします。
本番環境で下記のコードを入力しましょう。
グローバル IP アドレスが返ってくれば名前解決が出来ています。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ nslookup xxxxxxxxxx.com
Server:         10.0.0.2 
Address:        10.0.0.2#53 

Non-authoritative answer: 
Name:   xxxxxxxx.com 
Address: 54.178.156.248 
Name:   xxxxxxxx.com 
Address: 52.197.167.212 

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

ブラウザを開き、ドメイン名を入力し、インターネット経由でアクセスできるか確認します。

Welcome to nginx on the Amazon Linux AMI!と表示されていれば成功です。
ngnix.png

  • nginxの設定ファイルを編集

これではまだ、表示することができないので、nginxの設定ファイルを編集しましょう。
vimコマンドを使ってターミナル上で編集していきます。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf
rails.conf
upstream app_server {
  # sharedの中を参照するよう変更
  server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name <Elastic IPを記入> <ドメイン名>;

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

  # currentの中を参照するよう変更
  root /var/www/<アプリケーション名>/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    # currentの中を参照するよう変更
    root   /var/www/<アプリケーション名>/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;
}

注目すべきは8行目です。

rails.conf
server_name <Elastic IPを記入> <ドメイン名>;

ドメイン名が追加されていますね!

xxx.comの場合はserver_name <Elastic IPを記入> xxx.com

としましょう。escキーを入力後に:wqで上書き保存を忘れずに!

Elastic IPとドメイン名の間は必ず半角スペースを入力しましょう。

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

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

ブラウザをリロードし、ドメインで表示できていれば成功です。
できない場合、ブラウザのキャッシュを消去した後、ブラウザをリロードすれば表示できるかと存じます。

無料SSL化(Let's Encrypt)

無料のSSLサーバー証明書(以下、SSL証明書)であるLet’s Encryptは、米国の非営利団体であるISRG(Internet Security Research Group)により運営されています。全てのWebサイトを暗号化することを目指したプロジェクトであり、2019年6月現在では世界で1億枚以上の有効な証明書を発行しています。

非営利団体ということで財務基盤に不安を覚える方もいるかもしれませんが、現在ではFacebookやシスコシステムズ、Akamai Technologies、Verizonといった数多くの大手企業に支えられています。

Let’s Encryptでは、90日間有効なDV(Domain Validation)SSL証明書を2つの認証方式(ドメイン認証、DNS認証)で提供しています。SSL証明書は無料で提供されていますが、暗号強度などは一般的に販売されているSSL証明書と違いはありません。

ではレッツゴー!

  • certbotをクローン
ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ cd /usr/local

[ec2-user@ip-172-31-25-189 local]$ sudo git clone https://github.com/certbot/certbot

[ec2-user@ip-172-31-25-189 local]$ cd certbot
  • 証明書の作成を申請

申請するにあたって、Let's Encryptが認証するためのディレクトリを作成します。
(他の記事では/var/www/htmlなどとしている場合が多いですが、Amazon Linuxではデフォルトでそのようなディレクトリはないので、新たに作成します。)

ターミナル(EC2サーバー)
# ディレクトリ名は自由ですが、今回は letsencrypt-webroot とします。
[ec2-user@ip-172-31-25-189 ~]$ sudo mkdir /var/www/letsencrypt-webroot

さらに、nginxを書き換えます。

rails.conf
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf
rails.conf
upstream app_server {
  # sharedの中を参照するよう変更
  server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name <Elastic IPを記入> <ドメイン名>;

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

  # currentの中を参照するよう変更
  root /var/www/<アプリケーション名>/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    # currentの中を参照するよう変更
    root   /var/www/<アプリケーション名>/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;
  }

# 以下を追加(^~は前方一致です)
  location ^~ /.well-known/acme-challenge/ {
      root /var/www/letsencrypt-webroot;
    }

  error_page 500 502 503 504 /500.html;
}

その後、nginxを再起動します。

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

次に、以下のコマンドで認証可能かどうかを確認します。
(認証申請が1時間に5回Failすると、一定時間申請できなくなります(Rate Limits - Let's Encrypt - Free SSL/TLS Certificates)。そのため、先に認証可能かどうかを確認します。)

ターミナル(EC2サーバー)
# 【】の所は置き換えてください
[ec2-user@ip-172-31-25-189 ~]$ /usr/local/certbot/certbot-auto certonly --webroot --agree-tos --debug -m 【メールアドレス(例:○○@○○.com)】 -d 【ドメイン名(例:○○.com)】 -w /var/www/letsencrypt-webroot --dry-run

以下が出たら認証可能です。

ターミナル(EC2サーバー)
IMPORTANT NOTES:
 - The dry run was successful.

上のコマンドの--dry-runを外して認証申請をします。
(登録されたメールアドレスには、Let's Encryptからの通知(認証の有効期限が近づいてきた時の通知など)が届きます。)

ターミナル(EC2サーバー)
# 【】の所は置き換えてください
[ec2-user@ip-172-31-25-189 ~]$ /usr/local/certbot/certbot-auto certonly --webroot --agree-tos --debug -m 【メールアドレス(例:○○@○○.com)】 -d 【ドメイン名(例:○○.com)】 -w /var/www/letsencrypt-webroot

以下が出たら認証成功です。

ターミナル(EC2サーバー)
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/○○.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/○○.com/privkey.pem
   Your cert will expire on 2019-07-30. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

証明書が発行されたかを確認します。

ターミナル(EC2サーバー)
# 【】の所は置き換えてください
[ec2-user@ip-172-31-25-189 ~]$ sudo ls -lrth /etc/letsencrypt/live/【ドメイン名(例:○○.com)】/

以下が表示されればOKです。

ターミナル(EC2サーバー)
total 4.0K
-rw-r--r-- 1 root root 692 May  1 11:41 README
lrwxrwxrwx 1 root root  51 May  1 11:41 privkey.pem -> ../../archive/【ドメイン名(例:○○.com)】/privkey1.pem
lrwxrwxrwx 1 root root  53 May  1 11:41 fullchain.pem -> ../../archive/【ドメイン名(例:○○.com)】/fullchain1.pem
lrwxrwxrwx 1 root root  49 May  1 11:41 chain.pem -> ../../archive/【ドメイン名(例:○○.com)】/chain1.pem
lrwxrwxrwx 1 root root  48 May  1 11:41 cert.pem -> ../../archive/【ドメイン名(例:○○.com)】/cert1.pem

次に、nginxの設定ファイルをSSL用に更新します。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf
rails.conf
upstream app_server {
  server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/<ドメイン名>/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/<ドメイン名>/privkey.pem;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

  client_max_body_size 2g;

  root /var/www/<アプリケーション名>/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;

    root /var/www/<アプリケーション名>/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_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}

server {
  listen 80;
  server_name <ドメイン名>;
  return      301 https://$host$request_uri;
}

nginxを再起動します。

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

設定ファイルの更新はこれで最後になります。あと一息です!

  • ポート解放3

私はここで躓きました。
設定ファイルを更新して、「長い戦いが終わった(ニンマリ)」と意気揚々とリロードしたら、タイムアウトで表示されないじゃないか。

ふと、

ssl化のポート解放はあるのだろうかと、できているのだろうかと

閃いた。

やはり、ssl化に伴ってポートを開ける必要があるようです。

「セキュリティグループ」のリンクlaunch-wizard-1をクリックします。
7ee866ffd3f4791fc04ec4e7f820a260.png

「インバウンド」タブの中の「編集」をクリックします。
5668fc324ef4003048568c7ca675d2a0.png

スクリーンショット 2020-04-07 20.28.46.png

「ルールの追加」をクリックします。
タイプを「HTTPS」、プロトコルを「TCP」、ポート範囲を「443」、送信元を「カスタム / 0.0.0.0/0, ::/0」に設定します。「0.0.0.0」や「::/0」は「全てのアクセスを許可する」という意味です。

  • rails側の設定

ローカルで下記フォルダの記述を変更しましょう。

config/environments/production.rb(修正前)
# config.force_ssl = true
config/environments/production.rb(修正後)
config.force_ssl = true

変更後にmasterへpushしましょう。

ターミナル(ローカル)
# アプリケーションのディレクトリで実行する
$ bundle exec cap production deploy

以上でSSLの設定は完了です。
ブラウザからこのサイトにアクセスしてみましょう。https接続になるはずです。
また、http://として接続した場合でも、自動でhttps接続になるはずです。

  • Let's Encryptの自動更新

Let's Encryptの有効期間は3カ月と短いです。
自動で更新されるように、crontabで設定しておきましょう。

ターミナル(EC2サーバー)
[ec2-user@ip-172-31-25-189 ~]$ sudo crontab -u root -e # rootユーザーでcrontabを編集することにより、cronでsudoを使わなくて済むようになります。
crontab
0 4 1 * * /usr/local/certbot/certbot-auto --no-self-upgrade && service nginx restart

この例では、毎月1日午前4時に自動で更新されるようになります。

設定後、cronデーモンを再起動します。

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

上記の方法では Amazon Linux 2 でエラーが出るようです。
こちらの記事は Amazon Linux の程なのでご了承ください🙇‍♂️

最後に

最後までお付き合いいただき、ありがとうございました。
twitterやっておりますので是非フォローよろしくお願いいたします!
https://twitter.com/syomabusiness
youtubeも始める予定です!

13
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
18