⑨Rails環境変数  credentials  dotenv  .bash_profile 【初学者向け】

#はじめに
**本稿は、Rails環境変数は、credentials、dotenv、.bash_profile 
それぞれの実装方法を、初学者に向けてわかりやすく説明することを目標に書きました。**

当方、テックキャンプ卒業生で現在転職活動中です。
スクール受講当時は、環境変数はすごく難しく感じ、なかなか理解できずに来ました。
就活ポートフォリオなど、アプリケーションを本番環境にデプロイする時
環境変数の理解ができていないと、エラーやトラブルに直面し自己解決が大変です。
どこで設定した環境変数がどの引用文で機能しているか、把握する必要があります。

当方も初学者ゆえ理解度が及ばない点についてはご容赦ください。

#前提
AWS EC2
rbenv 1.1.2
ruby 2.5.1
Ruby on Rails 5.2
MySQL5.6
Gem unicorn デプロイ

#1. Rails5.2以降 credentials.yml.encで環境変数を設定するパターン
##Rails5.2~ credentials.yml.enc をざっくり説明
・config/master.keyの値は、credentials.yml.encの暗号、復号に使用されます
・config/master.keyの値が消えてしまうと、credentials.yml.encの復号ができずエラーになります
・config/master.keyは簡単に生成し直すことができます
・ローカルのconfig/master.keyは .gitignore(ギットイグノール)に初期設定されていてgitの監視から外れています
・EC2の本番環境に`$git clone`や`$git pull origin master`するとき、ローカルのconfig/master.key自体は移りません
・ローカル開発環境と同じように、本番環境でconfig/credentials.yml.encの環境変数を使用してアプリを起動させるには、手動でEC2にconfig/master.keyをコピーする作業が必要です
・config/credentials.yml.encひとつのファイルですべての環境変数を書くので複数の環境を運用するため、複数パターンの環境変数を持つ高度な作業では不便さを感じることもあるようです
・個人のポートフォリオ・デプロイ程度なら、credentials.yml.encは慣れれば便利だと思います


```ruby:credentials.yml.encで環境変数を設定する流れ
1)ローカルで credentials.yml.enc に環境変数を設定、復号を確認
2)GitHub リモートリポジトリに master push/merge
3)EC2に $git clone または $git pull origin master
4)EC2のアプリディレクトリに 手動で config/master.key をコピー
5)EC2で rails c で復号を確認
```

##ローカルで credentials.yml.enc に環境変数を設定、復号を確認
##config/credentials.yml.encの編集

```ruby:credentials.yml.encの環境変数の記述例
DATABASE_USER: root   環境変数 コロン 半角空白 値　(クオート囲み無し)
```

```ruby:(ローカル)config/credentials.yml.enc
#credentials.yml.encを編集するコマンド
EDITOR="vi" bin/rails credentials:edit
または
EDITOR="vim" bin/rails credentials:edit

i キー: インサートモード

# aws:
#   access_key_id: 123
#   secret_access_key: 345
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
#secret_key_base: fc6c7a8fb37aabccfba9dbee08b14d5ea6cced7ed5e1

#database.yml
DATABASE_USER: root   (←今回記述)
DATABASE_PASSWORD: password   (←今回記述)

#EC2 rake secretにて生成   
SECRET_KEY_BASE: 08bbe905f4dbcac971bfeacbc144105d623aa6a71    (←今回記述)

googlemap:
  MAP_SECRET_KEY: AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ   (←今回記述)

escキー : インサートモード解除
:wqキー : 上書き保存
```

##環境変数の復号を確認する

```ruby:環境変数の復号確認
呼び出しの形式 
"Rails.application.credentials.環境変数"
二行でインデントしている場合
"Rails.application.credentials.環境変数タイトル[:環境変数]"

$rails c  (コマンド実行)

[1] pry(main)> Rails.application.credentials.環境変数
=> “環境変数の値”
```

```ruby:環境変数の復号確認例
$rails c  (コマンド実行)

[1] pry(main)> Rails.application.credentials.DATABASE_USER
=> "root"
[2] pry(main)> Rails.application.credentials.DATABASE_PASSWORD
=> "password"
[3] pry(main)> Rails.application.credentials.googlemap[:MAP_SECRET_KEY]
=> "AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ"
```

##環境変数を実際に記述する


```ruby:credentials.yml.encに環境変数を１行で書いている場合
DATABASE_USER: root

呼び出しの形式 
Rails.application.credentials.DATABASE_USER 
```

```ruby:（ローカル）config/database.ymlの記述例

MySQLの設定
  username: <%= Rails.application.credentials.DATABASE_USER %>
  password: <%= Rails.application.credentials.DATABASE_PASSWORD %>
```

```ruby:credentials.yml.encに環境変数を2行でインデントして書いている場合
googlemap:
  MAP_SECRET_KEY: AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ

呼び出しの形式 
Rails.application.credentials.googlemap[:MAP_SECRET_KEY] 
```

```ruby:（ローカル）index.html.hamlの記述例
Googlemap APIの設定
%script{:async => "", :src => "https://maps.googleapis.com/maps/api/js?key=#{Rails.application.credentials.googlemap[:MAP_SECRET_KEY]}&callback=initMap"}
```
rails s してlocalhost:3000で正常に起動しているか確認します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617331/0bddad02-bbb7-be48-f95c-cb72ca65373b.png)


##ローカルのconfig/master.key の値をEC2側にコピーする

ローカルの環境変数設定が完了したので
gitリモートにpush/mergeして、EC2にgit clone/git pull origin master します


```ruby:EC2/SSHログイン
user@keisuke-sakagami-MacBook-Air .ssh % ssh -i nomadcafe_deproy.pem  ec2-user@＊＊.168.29.＊＊＊            

Last login: Mon May 18 00:00:05 2020 from om126133218239.21.openmobile.ne.jp

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

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-172-31-28-＊＊＊ ~]$ 
#ディレクトリ移動
$cd EC2アプリディレクトリトップ

#configディレクトリに移動
$cd config
#configディレクトリのファイル一覧表示
$ls
application.rb  boot.rb  cable.yml  credentials.yml.enc  database.yml  environment.rb  environments  initializers  locales  puma.rb  routes.rb  spring.rb  storage.yml  unicorn.rb

#master.keyファイルを作成(touchコマンド)
$touch master.key
#master.keyファイルができたか確認
$ls
~省略~
 master.key  puma.rb  routes.rb ....
~省略~

#master.keyファイルに値をコピペ(vi または vimコマンド)
$vim master.key
i キー: インサートモード
#ローカルのmaster.key値をコピペ
d9158f95432f3c44f39d93819550b529    (←今回コピペ)

escキー : インサートモード解除
:wqキー : 上書き保存

#master.keyファイルの内容を確認する(catコマンド)
$cat master.key 
d9158f95432f3c44f39d93819550b529
```
 こんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617331/e5af4c64-b101-ab71-ead3-1f20d041de3b.png)

##本番環境で環境変数の復号を確認する

```ruby:EC2/本番環境での環境変数の復号確認例

[ec2-user@ip-172-31-28-209 nomadcafe-sub]$ rails c

[1] pry(main)> Rails.application.credentials.DATABASE_USER
=> "root"
[2] pry(main)> Rails.application.credentials.DATABASE_PASSWORD
=> "password"
[3] pry(main)> Rails.application.credentials.googlemap[:MAP_SECRET_KEY]
=> "AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ"
```


```ruby:EC2/本番環境/unicorn-rails起動
 bundle exec unicorn_rails -c config/unicorn.rb -E production -D
```

無事、本番環境でアプリが起動しました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617331/13b72294-e159-bbf1-f7b6-0b9fc178778f.png)


#2. Gem dotenv(ドットエンヴ)で環境変数を設定するパターン

##dotenv(ドットエンヴ)をざっくり説明
・dotenvのみで環境変数を設定したり、または、credentials.yml.encと併用もできなくないが混乱する
・Gemをインストールして、.envファイルを手動で作成して.gitignoreするだけなので簡単です
・自分で.envファイルを.gitignoreに設定してgitの監視下から外す作業が必須です
・EC2の本番環境に`$git clone`や`$git pull origin master`してもEC2に.envファイルは移さないようにします
・本番環境で.envファイルの環境変数を使用するには、手動でEC2に.envファイルを作成して環境変数をコピーする必要があります
・ローカル修正→本番環境作業時に.envファイルの更新を失念すると、起動エラーで気づくことになる
・他者とのやりとりでは、dotenv派の方がいる場合もあるので、できるようになると良いかもです
・環境ごとに.env_development、.env_staging、.env_productionなどファイルと環境変数の値を分けておける利点がある


```ruby:dotenvで環境変数を設定する流れ
1)ローカルでgem 'dotenv-rails’をバンドルインストール
2)ローカルで.envファイルをディレクトリトップに手動で作成して環境変数を記述
3)ローカルで.envファイルを手動でgitignoreに追加
4)ローカルでrails c で環境変数の取り出しができるか確認
5)GitHub リモートリポジトリに master push/merge
6)EC2に $git clone または $git pull origin master
7)EC2のアプリディレクトリトップに手動で.envファイルを作成して環境変数をコピペ
8)EC2でrails c で環境変数の取り出しができるか確認
```

##.envファイルを作成して環境変数を設定する

##ローカルでgem 'dotenv-rails’をバンドルインストール

```ruby:Gemfile(ローカル)
gem 'dotenv-rails'

$bundle install 
  ```

##・ローカルで.envファイルをディレクトリトップに手動で作成して環境変数を記述

```ruby:ターミナル(ローカル)
#アプリディレクトリトップに移動
$cd アプリディレクトリ
#.envファイルを作成(touchコマンド)
$touch .env
#.envファイル作成できたか確認
$ls -a
```

##ローカルで.envファイルを手動でgitignoreに追加

```ruby:.gitignore(ローカル)
#一番下のあたりに記述
/.env    (←今回記述)
```

##.envファイルの編集   
     
```ruby:環境変数の記述例
DATABASE_USER= root   環境変数 イコール 値　(クオート囲み無し)
```
                      
```ruby:.envファイル(ローカル)
#database.yml
DATABASE_USER = root   (←今回記述)
DATABASE_PASSWORD = password   (←今回記述)

#googlemap API
MAP_SECRET_KEY= AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ   (←今回記述)

#本番環境用に、EC2側で rake secret コマンドを実行して新たにSECRET_KEY_BASEの値を生成したものです
SECRET_KEY_BASE=08bbe905f4dbcac971bfeac3f2ededa8f787e7728b9bba8128929f5ad486ab59015e7.....................   (←今回記述)
```


##ローカルでrails c で環境変数の取り出しができるか確認

```ruby:環境変数の取り出し
$rails c  (コマンド実行)
[1] pry(main)> ENV['環境変数']
=> “環境変数の値”
```


```ruby:.envの環境変数取り出し確認例

$rails 

[1] pry(main)> ENV['DATABASE_USER']
=> "root"
[2] pry(main)> ENV['DATABASE_PASSWORD']
=> "password"
[3] pry(main)> ENV['MAP_SECRET_KEY']
=> "AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ"
```

##環境変数を実際に記述する

```ruby:（ローカル）config/database.ymlの記述例

  username: <%= ENV['DATABASE_USER'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>
```

```ruby:（ローカル）index.html.hamlの記述例

Googlemap APIの設定
%script{:async => "", :src => "https://maps.googleapis.com/maps/api/js?key=#{ENV['MAP_SECRET_KEY']}&callback=initMap"}
```
rails s してlocalhost:3000で正常に起動しているか確認します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617331/f44221bd-084a-8ca6-8163-47c0df73ec92.png)

##EC2に手動で.envファイルを作成し、環境変数の値をコピーする

ローカルの環境変数設定が完了したので
gitリモートにpush/mergeして、EC2にgit clone/git pull origin master します

```ruby:EC2/SSHログイン
user@keisuke-sakagami-MacBook-Air .ssh % ssh -i nomadcafe_deproy.pem  ec2-user@＊＊.168.29.＊＊＊            

Last login: Mon May 18 00:00:05 2020 from om126133218239.21.openmobile.ne.jp

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

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-172-31-28-＊＊＊ ~]$ 

#ディレクトリ移動
$cd EC2アプリディレクトリトップ
#現在のファイル一覧を表示
$ls  -a
#.envファイルを作成(touchコマンド)
$touch .env
ファイルが作成できたか確認
$ls -a

#.envファイルにローカルの値をコピペ(vi または vimコマンド)
$vim .env
i キー: インサートモード
#ローカルの.envファイルの値をコピペ
escキー : インサートモード解除
:wqキー : 上書き保存

#.envファイルの中を表示して確認(catコマンド)
$cat .env
#database.yml
DATABASE_USER = root
DATABASE_PASSWORD = password
#googlemap API
MAP_SECRET_KEY= AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ
#EC2 rake secretにて生成
SECRET_KEY_BASE=08bbe905f4dbcac971bfeac3f2ededa8f787e7728b9bba8128929f5ad486ab59015e735............
```
##本番環境で環境変数の取り出しを確認する

```ruby:EC2/本番環境での環境変数の取り出し確認例
rails c 実行
[1] pry(main)> ENV['DATABASE_USER']
=> "root"
[2] pry(main)> ENV['DATABASE_PASSWORD'] 
=> "password"
[3] pry(main)> 
[4] pry(main)> ENV['MAP_SECRET_KEY']
=> "AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ"
```
こんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617331/d5192358-0696-8829-6741-2f2475e3be8d.png)


```ruby:EC2/本番環境/unicorn-rails起動
 bundle exec unicorn_rails -c config/unicorn.rb -E production -D
```
無事、本番環境でアプリが起動しました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617331/acd3ecf0-4938-94d9-df0b-b2533dc4a459.png)


#3. .bash_profile(バッシュプロファイル)で環境変数を設定するパターン

## .bash_profile(バッシュプロファイル)をざっくり説明
・credentials.yml.encやdotenvのRuby言語アプリ外のMac OS側で環境変数を設定します
・bash（バッシュ）はUNIX系シェル・コマンド言語、Linuxにおけるデファクトスタンダード(事実上の標準)、Linuxでコマンドの命令文を記述したシェルを実行するシェルスクリプト、「Bourne Again Shell」の略です
・bashでの環境変数設定はLinuxOSレベルでの標準的機能です
・アプリ外からデータ挿入する単純さ・アプリ言語非依存性・OS間可搬性、誤コミットリスク回避の大きなメリットです


```ruby:.bash_profileで環境変数を設定する流れ
1)ローカルで $envコマンド、または、 $export -pコマンド でシェル(bash)に存在する環境変数の一覧を表示
2)ローカルのユーザーのhomeディレクトリにある.bash_profile内に $exportコマンドで環境変数を設定
3)ローカルで $source ~/.bash_profileコマンド で環境変数を反映させる
4)ローカルで $rails c で環境変数の取り出しができるか確認
5)GitHub リモートリポジトリに master push/merge
6)EC2のhomeディレクトリにある.bash_profileに $exportコマンドで環境変数をコピペ
7)EC2で $source ~/.bash_profileコマンドで環境変数を反映させる
8)EC2で $rails c で環境変数の取り出しができるか確認
```

##.bash_profileにexportコマンドで環境変数を設定する

```ruby:.bash_profile(ローカル)
#ホームディレクトリに移動
$cd ~
#ホームディレクトリのファイル一覧表示
$ls -a
~省略~   
.bash_profile    .local    .......
~省略~   

#.bash_profile の中を表示
$cat .bash_profile  (違うディレクトリからの場合は cat ~/.bash_profile )/
#Terminal Japanese display setting
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

#.bash_profile にローカルの値をコピペ(vi または vimコマンド)
$vim .bash_profile (または $vim ~/.bash_profile)/
i キー: インサートモード
#export 半角空白 変数名=“値”  
export MAP_SECRET_KEY=AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ    (←今回記述)
escキー : インサートモード解除
:wqキー : 上書き保存

#環境変数を反映させる
$source .bash_profile  (違うディレクトリからの場合  $source ~/.bash_profile ) /

#シェルの環境変数を一覧表示して確認
$export -p
~省略~  
export MAP_SECRET_KEY=AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ
~省略~  

#echoコマンドで環境変数の取り出しを確認
$echo $MAP_SECRET_KEY
AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ
  ```

##環境変数の取り出しができるか確認

```ruby:環境変数の取り出し
$rails c  (コマンド実行)

[1] pry(main)> ENV['環境変数']
=> “環境変数の値”
```

```ruby:環境変数取り出し確認例
$rails c  

[1] pry(main)> ENV['MAP_SECRET_KEY']
=> "AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ"
```

##環境変数を実際に記述する

```ruby:index.html.haml（ローカル）
Googlemap APIの設定
%script{:async => "", :src => "https://maps.googleapis.com/maps/api/js?key=#{ENV['MAP_SECRET_KEY']}&callback=initMap"}
```

rails s してlocalhost:3000で正常に起動しているか確認します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617331/d702adb5-9d53-1b9a-847c-b68724e03851.png)


##EC2のhomeディレクトリにある.bash_profileにexportコマンドで環境変数をコピペする
ローカルの環境変数設定が完了したので
gitリモートにpush/mergeして、EC2にgit clone/git pull origin master します

```ruby:EC2/SSHログイン
user@keisuke-sakagami-MacBook-Air .ssh % ssh -i nomadcafe_deproy.pem  ec2-user@＊＊.168.29.＊＊＊            

Last login: Mon May 18 00:00:05 2020 from om126133218239.21.openmobile.ne.jp

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

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-172-31-28-＊＊＊ ~]$ 
#ホームディレクトリに移動
$cd ~
#ホームディレクトリのファイル一覧表示
$ls -a
~省略~   
 .bash_profile  .bashrc  .bundle   …
~省略~   

#.bash_profile の中を表示
$cat .bash_profile  (違うディレクトリからの場合 cat ~/.bash_profile)/
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
	. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin
export PATH
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

#.bash_profile にローカルの値をコピペ(vi または vimコマンド)
$vim .bash_profile  (または vim ~/.bash_profile )/
i キー: インサートモード
#export 半角空白 変数名=“値”  (ローカルのものをコピペ)
export MAP_SECRET_KEY=AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ    (←今回記述)
escキー : インサートモード解除
:wqキー : 上書き保存

#環境変数を反映させる
$source .bash_profile (違うディレクトリからの場合  source ~/.bash_profile)/

# シェルの環境変数を一覧表示して確認
export -p
~省略~  
export MAP_SECRET_KEY=AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ
~省略~  

#echoコマンドで環境変数の取り出しを確認
$echo $MAP_SECRET_KEY
AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ
```

##環境変数の取り出しができるか確認

```ruby:環境変数の取り出し
$rails c  (コマンド実行)

[1] pry(main)> ENV['環境変数']
=> “環境変数の値”
```


```ruby:EC2/本番環境での環境変数取り出し確認例
[ec2-user@ip-172-31-28-209 nomadcafe-sub]$ rails c

[1] pry(main)> ENV['MAP_SECRET_KEY']
=> "AIzaSyDbL~~~~~~~~Bi9S_ZqSTlqQ"
```
こんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617331/c879e5ae-7dd2-36fc-3217-40bfab47e6c7.png)




```ruby:EC2/本番環境/unicorn-rails起動
 bundle exec unicorn_rails -c config/unicorn.rb -E production -D
```

無事、本番環境でアプリが起動しました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617331/8b6cbbec-3547-1cd3-d331-466e97ae539b.png)



#4.最後に
dockerコンテナ環境でのデプロイを一旦やめて、
CI/CDについて学習するべくスクールで学んだunicornデプロイを復習したところです。

これからも、学習したことを初学者の視点でわかりやすい記事にしてアウトプットしていこうと思います。