😀

EC2でのDocker環境の構築(ArgumentError: Missing `secret_key_base`、My

2020/12/29に公開

はじめに

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

エラー①

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

エラー②

ターミナル
$ 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に基づいて行っていきます。

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

ターミナル(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コマンドが使えるようになります。

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

なぜグループに追加するかは【Docker】 ERROR: Couldn’t connect to Docker daemon at http+docker://localhost – is it running? を参考にしてください。

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

Install Docker Compose - Docker Documentation に基づき作業していきます。

ターミナル(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環境を構築してみたを参考にして進めました。

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

ターミナル(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し、本番環境にも適用させましょう。

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

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

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

以下のようになれば成功です。

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

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

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

ターミナル(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'を参考にしました。

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

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

ターミナル(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コマンドで削除されている確認してみましょう

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

ターミナル(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の設定を変更していたためです。

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') %>
.env
DB_USERNAME='root'
DB_PASS='password'
DB_HOST='db'
MYSQL_ROOT_PASS='password'

.envでの環境変数設定はこちらを見てみてください。

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

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

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

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を実行します。

ターミナル(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環境を構築してみた
AWS EC2 Amazon LinuxでDocker, Docker Composeをインストールする
(AWS) ArgumentError: Missing 'secret_key_base' for 'production' environment, set this string with 'rails credentials:edit'

Discussion