docker compose環境のrailsでDB関連のエラーが出て確認したこと
環境
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