📝

docker compose環境のrailsでDB関連のエラーが出て確認したこと

2022/03/08に公開

環境

docker compose
mysql
rails6
rails初心者が色々迷走しているうちに様々なエラーに出会ったのでまとめてみます。
他にもあればコメントいただけたら嬉しいです。

そもそもコンテナが立ち上がらない場合

railsのWebサーバが立ち上がっていない状態です。

$ docker compose up -d
$ docker container ls
cfxxxxxxa776   mysql:5.7    "docker-entrypoint.s…"   1 minutes ago   Up 1 minutes   0.0.0.0:3306->3306/tcp, 33060/tcp   webapp-db-1

対応方法

/tmp/pids/server.pid
というファイルを削除しコンテナを再度立ち上げると無事ウェブサーバが立ち上がりました。

エラー

データベースがない時に出るエラーです。

ActiveRecord::NoDatabaseError: Unknown database

対応

データベースがあるかを確認します。

#execコマンドでrailsコンテナの中に入ります。
$ docker exec -it containerid bash
#railsコンテナの中からmysqlコンテナに接続しつつmysqlを立ち上げます。
root@xxxxxxxxxx:/app# mysql -u root -p -h db
#ここでmysqlが立ち上がらない場合そもそもdockerコンテナ同士の通信がうまく行っていないので下の「dockerコンテナ間の通信を確認する」を見てください。
#mysqlが立ち上がった場合はshow databasesでデータベースがあるか確認します。
#データベース名はrailsアプリの/config/database.ymlで
#database: rails_sample_dvなどと記載されています。
MySQL [(none)]> show databases;
#データベースがなかった場合は作成します。
MySQL [(none)]>exit
root@xxxxxxxxxx:/app# rails db:create
root@xxxxxxxxxx:/app# rails db:migrate

これでデータベースが作成されるので0.0.0.0:3000などでアクセスができるようになります。

dockerコンテナ間の通信を確認する

docker-compose.ymlの設定を確認します。
以下db接続関連の項目のみを書き出してみます。
これらがない場合は書き足してみてdockerを再構築
(環境によってはimage、volumeを削除してdocker compose build --no-cacheなどとすると確実かもしれません。)
してみて再度ウェブコンテナからmysqlに接続できるかを確認します。

version: "3"
services:
  app:
    depends_on:
      - mysql
  mysql:
    volumes:
      - mysql-volume:/var/lib/mysql
    environment:
      - MYSQL_ALLOW_EMPTY_PASSWORD=yes
    ports:
      - "3306:3306"
volumes:
  mysql-volume:

railsのdatabase.ymlの記述が間違っていたときのエラー

自分の場合は以下のエラーがブラウザでアクセスした時に出ました。

#error1
ActiveRecord::ConnectionNotEstablished
No connection pool for 'ActiveRecord::Base' found.
#error2
Puma caught this error: Cannot load database configuration:

そしてその状態でrails consoleを立ち上げようとして以下のエラーに遭遇

#error3
webapp/config/database.yml:33:in `<main>': Cannot load database configuration:
undefined method `[]' for nil:NilClass (NoMethodError)

ちなみにその時のdatabase.ymlは以下

#database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: 5
  timeout: 3306
  host: mysql
development:
  <<: *default
  username: root
  host: mysql
  database: rails_sample_dv
  socket: /tmp/mysql.sock
# test:
#   <<: *default
#   username: root
#   host: <%= ENV['DB_HOST'] %>
#   database: rails_sample_dv
#   socket: /tmp/mysql.sock
# production:
#   <<: *default
#   username: <%= Rails.application.credentials.db[:user] %>
#   host: <%= Rails.application.credentials.db[:host] %>
#   password: <%= Rails.application.credentials.db[:password] %>
#   database: <%= Rails.application.credentials.db[:name] %>

これはなぜかコメントアウトしている行が読み込まれているようで
以下のようにコメントアウトしている部分を削除したらとりあえずエラーは解消されました。

#database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: 5
  timeout: 3306
  host: mysql
development:
  <<: *default
  username: root
  host: mysql
  database: rails_sample_dv
  socket: /tmp/mysql.sock

master.key、credentials.yml.encを作り直してみる

railsアプリの/configディレクトリにmaster.key、credentials.yml.encというファイルがあります。
これらがなかったり、なんらかの影響で変更されたりした場合railsアプリが立ち上がらない場合があります。
そんな時は念の為2つのファイルをバックアップしてから
作成し直すことでアプリが立ち上がる場合もあります。
作成し直す際は前述同様docker execコマンドでrailsコンテナにログインしてから以下のコマンドで再生成します。

EDITOR=vim rails credentials:edit

場合によってはsudoをつけたほうが良いかもしれません。

そもそもmaster.key、credentials.yml.encとは?

いわゆるサーバで設定する環境変数をrails内で設定できるという仕組みで
master.key(秘密鍵)、credentials.yml.enc(公開鍵)といった具合に
1組の対になっています。
ですから何らかの拍子で一つが変わったりする場合エラーになります。
またmaster.keyは必ず.gitignoreなどに記載し、公開されないように
デプロイツールに登録しなければなりません。

余談

appコンテナ内で
buncle exec rails db:create
などとコマンドを実行する際
appコンテナにmysqlコマンド、mysqlクライアントは必要ありません。
自分は一瞬必要なのか?と思ってしまいました^^;

% mysql --version
% not found mysql

↑の状態でも実行できます。

Discussion