EC2でのDocker環境の構築(ArgumentError: Missing `secret_key_base`、Mysql2::Error::ConnectionError: Access denied for user 'root'@'172.18.0.4' (using password: NO)の解決法)　

# はじめに
EC2インスタンスを使用してインフラ構築しようとしたら、DB作成の時に以下２つのエラー沼にハマったので、その解決とDocker・docker-composeを用いたEC2によるデプロイのDB作成までの流れを解説します。

**エラー①**

```ruby:ターミナル
$ docker-compose run web rails db:create RAILS_ENV=production

ArgumentError: Missing `secret_key_base` for 'production' environment, set this string with `rails credentials:edit’
```

**エラー②**

```ruby:ターミナル
$ docker-compose run web rails db:create RAILS_ENV=production

Mysql2::Error::ConnectionError: Access denied for user 'root'@'172.18.0.4' (using password: NO)
```

# 開発環境

Ruby 2.6.5
Bundler 2.1.4
Rails 6.0.0
MySQL 5.6.50

# 前提

この記事での作業を行うにあたり、前提として開発環境・EC2にDocker及びdocker-composeがインストールされていることを前提とします。

ここではEC2におけるDockerとdocker-composeのインストールだけ解説します。

# EC2へのDockerインストール
作業内容は[Docker の基本 - Amazon EC2 Container Service](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/docker-basics.html)に基づいて行っていきます。

次にDockerをインストールしていきます。

```ruby:ターミナル(EC2内)
# yum の更新
$ sudo yum update -y

# yum から docker をインストール
$ sudo yum install -y docker

# docker サービスの起動
$ sudo service docker start
Starting cgconfig service:                                 [  OK  ]
Starting docker:                                           [  OK  ]

# ec2-user を docker　グループに追加する
$ sudo usermod -a -G docker ec2-user
```
一度ログアウトし、再度ログインすると`docker`コマンドが使えるようになります。

```ruby:ターミナル(EC2内)
$ docker info
```

なぜグループに追加するかは[【Docker】 ERROR: Couldn’t connect to Docker daemon at http+docker://localhost – is it running?](https://qiita.com/dnnnn_yu/items/14a31721a2870b735938)　を参考にしてください。

# EC2へのDocker Composeのインストール

[Install Docker Compose - Docker Documentation ](https://docs.docker.com/compose/install/)に基づき作業していきます。

```ruby:ターミナル(EC2)
# 一時的にスーパーユーザーになる
$ sudo -i

# ここから一時的にスーパーユーザー
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# docker-compose コマンドに実行権限付与
$ chmod +x /usr/local/bin/docker-compose

# スーパーユーザーを抜ける
$ exit

# docker-compose コマンドの実行確認
$ docker-compose --version
docker-compose version 1.11.2, build dfed245
```

# EC2のDocker内にDB作成

ここからは[ec2にdocker環境を構築してみた](https://qiita.com/Fumy72676433/items/53f55b866d32a7aa0c16)を参考にして進めました。

まずdockerコンテナを作成し、バックグラウンドで起動します。

```ruby:ターミナル(EC2内)
# コンテナ作成(バックグラウンドで起動)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose up -d 

# 起動しているか確認
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker ps -a
```

起動できていたら、いよいよ本題のDBを作成していきます。

作成前に**必ずリモートの変更をcommit→push**し、**本番環境にも適用させましょう。**

```ruby:ターミナル(EC2内)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ git pull origin master
```

続いてDBを作成していきます。

```ruby:ターミナル(EC2内)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose run web rails db:create RAILS_ENV=production
```
以下のようになれば成功です。

```ruby:ターミナル(EC2内)
created database 'アプリ名_production'
```

順当に行けば、このようになりますが、僕の場合は、以下のエラーが出ました。

## エラー① ArgumentError: Missing `secret_key_base` for 'production' environment, set this string with `rails credentials:edit’

```ruby:ターミナル(EC2内)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose run web rails db:create RAILS_ENV=production

ArgumentError: Missing `secret_key_base` for 'production' environment, set this string with `rails credentials:edit’
```

このエラーの解決には[(AWS) ArgumentError: Missing 'secret_key_base' for 'production' environment, set this string with 'rails credentials:edit'](https://mattun-programming.hatenablog.com/entry/2020/01/16/123811)を参考にしました。

エラー原因は`config/credentials.yml.enc`というファイルがローカル環境と本番環境であっていないため上記エラーが発生するようです。

なので**本番環境(EC2)**で一度、`credentials.yml.enc`ファイルを削除して作り直すことで解決することができるようです。

```ruby:ターミナル(EC2内)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ cd /var/www/アプリ名/config

[ec2-user@ip-XXX-XX-XX-XXX config]$ ls
application.rb       database.yml    locales    storage.yml
boot.rb              environment.rb  puma.rb    unicorn.rb
cable.yml            environments    routes.rb  webpack
credentials.yml.enc # このファイル  
initializers    spring.rb  webpacker.yml

[ec2-user@ip-XXX-XX-XX-XXX config]$ rm credentials.yml.enc
# rmコマンドで削除

# lsコマンドで削除されている確認してみましょう

```

無事削除できていたら作成し直しましょう。

```ruby:ターミナル(EC2内)
[ec2-user@ip-XXX-XX-XX-XXX config]$　EDITOR=vim rails credentials:edit

Adding config/master.key to store the encryption key: 54xx0x9xx86x4x754x9x0xxxxx10x492

Save this in a password manager your team can access.

If you lose the key, no one, including you, can access anything encrypted with it.

      create  config/master.key

File encrypted and saved.

# create と save ができていれば成功
```

よし、これで解決した！！
DB作成だ！！と思い、作成するコマンドを実行すると、今度は次のようなエラーが出ました。

## エラー② Mysql2::Error::ConnectionError: Access denied for user 'root'@'172.18.0.4' (using password: NO)

エラー内容を要約すると**「DBにログインするためのパスワードがないよ」**と怒っているということになります。

ここで僕はDockerのコンテナを削除したり、停止・再起動したり、作り直したりと、色々やりましたが、解決できず沼にハマりました(笑)

原因は`database.yml`に記述した、本番環境(production)の記述でした。

それもそのはずで、Docker導入のために`database.yml`の設定を変更していたためです。

```ruby:config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

# ここから設定変更
  username: <%= ENV.fetch('DB_USERNAME', 'root') %>
  password: <%= ENV.fetch('DB_PASSWORD', 'password') %>
  socket: /tmp/mysql.sock
  host: <%= ENV.fetch('DB_HOST', 'db') %>
```

```ruby:.env
DB_USERNAME='root'
DB_PASS='password'
DB_HOST='db'
MYSQL_ROOT_PASS='password'
```

`.env`での環境変数設定は[こちら](https://qiita.com/sc30gsw/items/f85ab4eaf4ca8164b3b0)を見てみてください。

ローカルでの設定は上記のようになっていますが、本番環境では下記のようになっています。

```ruby:config/database.yml
production:
  <<: *default
  database:アプリ名_production
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock
```

つまり、このままの記述ではローカルと本番でのデーターベースに差異が生まれており、データーベースを作れないということになります。
この本番環境の記述とローカルの記述を合わせることで、このエラーは解決できます。

```ruby:config/database.yml
production:
    <<: *default
    database: tumlog_production
    host: <%= ENV.fetch('DB_HOST', 'db') %>
    username: <%= ENV.fetch('DB_USERNAME', 'root') %>
    password: <%= ENV.fetch('DB_PASSWORD', 'password') %>
    socket: /var/lib/mysql/mysql.sock
```

以上のように記述し直したら、**gitでcommit→push**しターミナルで**git pull origin master**を実行します。

```ruby:ターミナル(EC2内)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ git pull origin master
* branch            master     -> FETCH_HEAD
   6f883e9..99c894d  master     -> origin/master
Updating 6f883e9..99c894d
Fast-forward
 config/database.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose run web rails db:create RAILS_ENV=production

created database 'アプリ名_production'
```

以上のように本番環境でDBを作成できました。
最後に、意外と忘れがちなのが**git pull origin master**なので、それを忘れて、自分からエラー沼にはまらないようにしましょう(笑)


# 参考文献

① [ec2にdocker環境を構築してみた](https://qiita.com/Fumy72676433/items/53f55b866d32a7aa0c16)
②[AWS EC2 Amazon LinuxでDocker, Docker Composeをインストールする](https://qiita.com/shinespark/items/a8019b7ca99e4a30d286)
③ [(AWS) ArgumentError: Missing 'secret_key_base' for 'production' environment, set this string with 'rails credentials:edit'](https://mattun-programming.hatenablog.com/entry/2020/01/16/123811)