Heroku上にアプリケーションを作成しよう

Herokuにアプリケーションを作成し
-

|heroku createコマンド|
|--|
Heroku上に公開するアプリケーションを作成します。＊すでに登録されているアプリケーション名は使用できません。

```rb:ターミナル
% cd ~/projects/ajax_app
% pwd
#「ajax-app」にいることを確認する
% heroku create ajax-app
```

|ClearDBアドオン|
|--|
ClearDBアドオンとは、MySQLを使うためのツールです。ClearDBというデータベースサービスが提供しているアドオンで、これを追加することにより、HerokuでMySQLを使用可能となります。

```rb:ターミナル
% heroku addons:add cleardb
Creating cleardb on ⬢ ajax-app... free
Created cleardb-vertical-00000 as CLEARDB_DATABASE_URL
Use heroku addons:docs cleardb to view documentation
```
これでデータベースをMySQLに設定できました。Ruby on Railsを使う場合は、MySQLに対応するGem設定を変更します。

```rb:ターミナル
% heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL`
```

これでClearDBデータベースのURLを変数heroku_cleardbに格納できました。

```rb:ターミナル
% heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}
```

```rb:以下、コマンドの実行結果
Setting DATABASE_URL and restarting ⬢ ajax-app... done, v◯◯
DATABASE_URL: mysql2://000000000000:0aa0000@us-cdbr-east-02.cleardb.com/heroku_aaa00000000?reconnect=true
```

Heroku上で非公開の値を管理する仕組み
-

アプリケーションを開発する際、サーバーのアクセスキーやAPIキーなど、外部に漏らしたくない情報を扱う場面があります。デプロイをする際、それらの情報はセキュリティの観点から暗号化する必要があります。暗号化された情報は、開発環境および本番環境であらかじめ用意した鍵を用いて復号（暗号化された情報を使えるように）します。


Railsのバージョン5.2以降では、credentials.yml.encを利用して、それらの情報を暗号化します。

###credentials.yml.encファイル
 Railsにて、外部に漏らしたくない情報を扱う際に用いるファイルです。通常時は、英数字の文字列で構成された暗号文が表示され、ファイル内に何が書かれているのか分からないようになっています。しかし、このcredentials.yml.encと対になるmaster.keyが存在する場合、credentials.yml.encの暗号文を復号し、ファイル内の記述を確認できます。

 master.keyファイル
 credentials.yml.encの暗号文を復号する、鍵の役割を持ったファイルです。特定のcredentials.yml.encと対になっているため、その他のcredentials.yml.encへは、効果を発揮しません。
 また、master.keyは非常に重要なファイルなので、リモートリポジトリに反映されることは好ましくありません。そのため、デフォルトで.gitignoreに記述されており、Gitで管理されない仕組みになっています。


 credentials.yml.encの中身を確認しましょう
-

まずは、ターミナルのAjaxAppディレクトリにて、下記のコマンドを入力しましょう。
下記のコマンドは、credentials.yml.encをmaster.keyによって復号し、中身を確認するためのコマンドです。

```rb:ターミナル
% EDITOR="vi" bin/rails credentials:edit
```

 以下のような画面が確認できれば、credentials.yml.encをmaster.keyによって復号し、中身を確認できた状態と言えます。

 次に、他のファイルと同様の方法で、credentials.yml.encの中身を確認してみましょう。
テキストエディタにてAjaxAppディレクトリを開き、config/credentials.yml.encを開きましょう。
先ほど確認した内容と異なり、以下の様な暗号文のみが確認できます。

credentials.yml.encは、master.keyを用いない場合には暗号文として表示されること
credentials.yml.encは、master.keyとセットで扱うことで中身が解読可能になること
このように、credentials.yml.encはmaster.keyとセットで扱います。

しかし、先にお伝えしたように、セキュリティの面から、master.keyはデフォルトでGitに管理されない仕組みとなっています。

この後、HerokuへAjaxAppのコードをデプロイしますが、その際にデプロイされるコードというのは、Gitで管理されているコードになります。つまり、master.keyはこのままだとHeroku上へデプロイできず、credentials.yml.encもHeroku上で扱えないということになります。

そこで、Heroku上に別途master.keyを設置し、Heroku上でもcredentials.yml.encを扱えるようにしましょう。

Heroku上にmaster.keyを設置しよう
-

Heroku上には、環境変数としてmaster.keyの値を設置します。Herokuへ環境変数を設定するためには、 heroku configというコマンドを使用します。

###環境変数
OSが提供するデータ共有機能の1つで、「どのディレクトリ・ファイルからでも参照できる変数」を設けることができます。一般的な用途の1つとして、「外部に漏らしたくない情報を環境変数にセットする」というものがあります。

環境変数のイメージとしては、特定の値を格納する箱を思い浮かべましょう。今回は、RAILS_MASTER_KEYという環境変数（箱）を用意し、その中にmaster.keyの値を入れるという使い方をします。この様に設定をすると、外部にmaster.keyの値を漏らすことなく、使用できます。
その環境変数を設定するためには、heroku configというコマンドを使用します。

|heroku configコマンド|
|--|
Heroku上で環境変数の参照・追加・削除等をする場合に用います。環境変数の追加であればheroku config:set 環境変数名="値"と実行します。そうすることによって、Heroku上で環境変数を追加できます。

Heroku上で環境変数を設定しましょう
-

Heroku上に環境変数を設定します。

```rb:ターミナル
% heroku config:set RAILS_MASTER_KEY=`cat config/master.key`
```

 Heroku上で環境変数を確認しましょう
設定が正しくできているか、Herokuの環境変数一覧を表示してみましょう。下記のコマンドを入力してください。

```rb:ターミナル
% heroku config
```

以下のように、RAILS_MASTER_KEYという変数名で値が設定されていれば成功です。

動作環境を変更しよう
-

デプロイをする前に、Herokuで利用する環境を指定しましょう。Herokuには、Stack（スタック）という環境が用意されています。

 Stack
-

 Stackとは、Herokuにおけるアプリケーションの動作環境のことです。Stackはデプロイされたアプリケーションを読み取り正常に稼働させるために用意されています。デフォルトのStackは「Heroku-20」です。一方で、別のStackを選択することもできます。

みなさんが開発に使用してきたRubyのバージョンは、Heroku-20では使用できません。
そのため、Rubyのバージョン2.6.5が動作するStackを指定しましょう。

 Herokuで利用するStackを指定しましょう
-

```rb:ターミナル
% heroku stack:set heroku-18 -a ajax-app
```

 既にHerokuへpush済みの方へ。2021年1月に、HerokuのStackがHeroku-18からHeroku-20へと更新されました。そのため、以前にデプロイをされた方でも、デプロイの際に「The Ruby version you are trying to install does not exist on this stack.」とエラーが出てしまう場合は、上記のコマンドを実行しましょう。
Herokuへアプリケーションを追加しよう.
 Herokuにデプロイする際には、Gitの仕組みを使用するのでした。Gitで管理しているリポジトリをHerokuへ反映することで、Heroku上で該当するアプリケーションの操作が可能になります。Gitで管理しているリポジトリをHerokuに反映するためにはgit push heroku masterというコマンドを用います。

 git push heroku masterを実行しましょう
-

下記のコマンドを入力し、HerokuへAjaxAppの情報を追加しましょう。


```rb:ターミナル
% git push heroku master
```

git push heroku master 実行時に「remote: ! Could not detect rake tasks」「remote: ! ensure you can run $ bundle exec rake -P against your app」とエラーが表示される場合は、こちらをご確認ください。
>https://qiita.com/takuo_maeda/items/267d38f7dfc23bc4e41f

今後、開発環境のAjaxAppに追加機能を実装し、その変更をHeroku上のAjaxAppにも反映したい場合は、同じ様にmasterブランチにコミットし、Herokuにプッシュする必要があります。



Heroku上でマイグレーションファイルを実行しよう
-

 Herokuにアプリケーションの情報を反映することができました。しかし、データベースにはマイグレーションの情報が反映されていません。rails db:migrateを実行したいところですが、そのままコマンドを入力しても実行できません。Heroku上で実行したいコマンドの頭には、heroku runをつけましょう。

 heroku runコマンド
-

Heroku上で実行したいコマンドに用います。rails db:migrateであればheroku run rails db:migrateと実行します。そうすることによって、Heroku上でコマンドが実行できます。


```rb:ターミナル
% heroku run rails db:migrate

Running rails db:migrate on ⬢ ajax-app-123456... up, run.8920 (Free)
D, [2020-05-08T08:22:50.410454 #4] DEBUG -- :    (2.9ms)  SET NAMES utf8mb4,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
D, [2020-05-08T08:22:50.467023 #4] DEBUG -- :    (2.6ms)  SELECT @@innodb_file_per_table = 1 AND @@innodb_file_format = 'Barracuda'
D, [2020-05-08T08:22:50.479166 #4] DEBUG -- :    (11.6ms)  CREATE TABLE `schema_migrations` (`version` varchar(255) NOT NULL PRIMARY KEY)
D, [2020-05-08T08:22:50.499390 #4] DEBUG -- :    (12.0ms)  CREATE TABLE `ar_internal_metadata` (`key` varchar(255) NOT NULL PRIMARY KEY, `value` varchar(255), `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL)
D, [2020-05-08T08:22:50.504699 #4] DEBUG -- :    (2.4ms)  SELECT GET_LOCK('410119075843185555', 0)
D, [2020-05-08T08:22:50.525145 #4] DEBUG -- :    (2.8ms)  SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
I, [2020-05-08T08:22:50.527632 #4]  INFO -- : Migrating to CreatePosts (20200407082548)
== 20200407082548 CreatePosts: migrating ======================================
-- create_table(:posts)
D, [2020-05-08T08:22:50.545176 #4] DEBUG -- :    (11.5ms)  CREATE TABLE `posts` (`id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, `content` text, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL)
   -> 0.0126s
== 20200407082548 CreatePosts: migrated (0.0128s) =============================

D, [2020-05-08T08:22:50.559351 #4] DEBUG -- :    (2.4ms)  BEGIN
D, [2020-05-08T08:22:50.562044 #4] DEBUG -- :   primary::SchemaMigration Create (2.5ms)  INSERT INTO `schema_migrations` (`version`) VALUES ('20200407082548')
D, [2020-05-08T08:22:50.573840 #4] DEBUG -- :    (11.5ms)  COMMIT
D, [2020-05-08T08:22:50.584601 #4] DEBUG -- :   ActiveRecord::InternalMetadata Load (3.2ms)  SELECT `ar_internal_metadata`.* FROM `ar_internal_metadata` WHERE `ar_internal_metadata`.`key` = 'environment' LIMIT 1
D, [2020-05-08T08:22:50.595802 #4] DEBUG -- :    (2.5ms)  BEGIN
D, [2020-05-08T08:22:50.598379 #4] DEBUG -- :   ActiveRecord::InternalMetadata Create (2.4ms)  INSERT INTO `ar_internal_metadata` (`key`, `value`, `created_at`, `updated_at`) VALUES ('environment', 'production', '2020-05-08 08:22:50', '2020-05-08 08:22:50')
D, [2020-05-08T08:22:50.607963 #4] DEBUG -- :    (9.4ms)  COMMIT
D, [2020-05-08T08:22:50.610566 #4] DEBUG -- :    (2.4ms)  SELECT RELEASE_LOCK('410119075843185555')
```