rake db:create時のMySQLのエラー対応
はじめに
Ruby on RailsとMySQLの環境構築時にrake db:createでMySQLのエラーに何度か遭遇することがありました。今後どこかで同じエラーに遭遇しそうなので、備忘録として残します。
使用バージョン
- Ruby: 2.4.10
- Ruby on Rails: 4.2.10
- MySQL: 5.7
- Docker Desktop for Mac: 3.3.1
MySQLのエラー
Mysql2::Error: Access denied for user
条件
Ruby on Railsのdatabase.yml、MySQLのDockerfile、docker-compose.ymlは以下のとおりです。
default: &default
adapter: mysql2
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: mysql_user
password: mysql_user
host: mysql
database: sampledb
socket: /tmp/mysql.sock
timeout: 5000
development:
<<: *default
test:
<<: *default
database: sampledb_test
FROM mysql:5.7
ENV MYSQL_ROOT_PASSWORD password
ENV MYSQL_USER mysql_user
ENV MYSQL_PASSWORD mysql_user
ENV TZ 'Asia/Tokyo'
ADD ./my.cnf /etc/mysql/conf.d/my.cnf
CMD ["mysqld"]
version: '3'
services:
mysql:
build:
context: ./db
dockerfile: Dockerfile
volumes:
- ./db/data:/var/lib/mysql
ports:
- 3306:3306
rails:
build:
context: ./rails
dockerfile: Dockerfile.alpine
volumes:
- ./rails:/app/
ports:
- '3000:3000'
depends_on:
- mysql
このコードを使用して、docker-compose -f docker-compose.yml run --rm rails bash
を行い、railsコンテナ内でbundle exec rake db:create
を行います。
現象
Mysql2::Error: Access deniedが発生しました。
bash-5.0# bundle exec rake db:create
Mysql2::Error: Access denied for user 'mysql_user'@'%' to database 'sampledb': CREATE DATABASE `sampledb` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`
/usr/local/bundle/gems/mysql2-0.4.10/lib/mysql2/client.rb:120:in `_query'
/usr/local/bundle/gems/mysql2-0.4.10/lib/mysql2/client.rb:120:in `block in query'
・・・略・・・
Couldn't create database for {"adapter"=>"mysql2", "pool"=>5, "username"=>"mysql_user", "password"=>"mysql_user", "host"=>"mysql", "database"=>"sampledb", "socket"=>"/tmp/mysql.sock", "timeout"=>5000}
Mysql2::Error: Access denied for user 'mysql_user'@'%' to database 'sampledb_test': CREATE DATABASE `sampledb_test` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`
/usr/local/bundle/gems/mysql2-0.4.10/lib/mysql2/client.rb:120:in `_query'
/usr/local/bundle/gems/mysql2-0.4.10/lib/mysql2/client.rb:120:in `block in query'
・・・略・・・
原因
Ruby on Railsのdatabase.ymlにある、データベースへの接続情報が間違っているためです。ここではMySQLのMYSQL_USERとMYSQL_PASSWORDの値を、Ruby on Railsのユーザ名とパスワードにセットしていました。
そのため、database.ymlのユーザ名をrootとし、パスワードをMYSQL_ROOT_PASSWORDの値(password)に変更することで解決できます。
補足:なぜユーザをrootに変えることで解決できるのか
今回のMySQLコンテナではroot以外のユーザに権限を与えていません。
そのため、MySQLコンテナでデータベースを作成できる権限を持つのはrootのみとなります。
実際にMySQLコンテナにrootユーザで入って、権限を確認してみると、rootのみ権限が付与されていることが分かります。
$ mysql -h 127.0.0.1 -u root -p
mysql> show grants;
+-------------------------------------------------------------+
| Grants for root@% |
+-------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION |
+-------------------------------------------------------------+
1 row in set (0.00 sec)
Mysql2::Error: Can't create database
条件
Ruby on Railsのdatabase.yml、MySQLのDockerfile、docker-compose.ymlは、上記「Mysql2::Error: Access denied for user」項目と同じになります。
ただし、database.ymlのユーザ名はroot、パスワードはrootユーザのパスワードとなります。
現象
Mysql2::Error: Can't create databaseが発生しました。
bash-5.0# bundle exec rake db:create
Mysql2::Error: Can't create database 'sampledb' (errno: 1777999232): CREATE DATABASE `sampledb` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`
/usr/local/bundle/gems/mysql2-0.4.10/lib/mysql2/client.rb:120:in `_query'
/usr/local/bundle/gems/mysql2-0.4.10/lib/mysql2/client.rb:120:in `block in query'
・・・略・・・
Couldn't create database for {"adapter"=>"mysql2", "pool"=>5, "username"=>"root", "password"=>"password", "host"=>"mysql", "database"=>"sampledb", "socket"=>"/tmp/mysql.sock", "timeout"=>5000}
Mysql2::Error: Can't create database 'sampledb_test' (errno: 1777999232): CREATE DATABASE `sampledb_test` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`
/usr/local/bundle/gems/mysql2-0.4.10/lib/mysql2/client.rb:120:in `_query'
/usr/local/bundle/gems/mysql2-0.4.10/lib/mysql2/client.rb:120:in `block in query'
・・・略・・・
Couldn't create database for {"adapter"=>"mysql2", "pool"=>5, "username"=>"root", "password"=>"password", "host"=>"mysql", "database"=>"sampledb_test", "socket"=>"/tmp/mysql.sock", "timeout"=>5000}
原因
MySQLへの接続はできているようですが、データベースの作成ができていないようです。
作成できない原因の1つとして、作成するスペースがないためです。
docker volumeコマンドで確かめてみると、不要なvolumeが大量に残っていました。
$ docker volume ls
DRIVER VOLUME NAME
local 2a75c2409d8d2ef9c66d276e75bbd3d4338d6b77719378e17d4e992c4df132cc
local 2d3fa031084aa6630d92279e1992d222a41590c2993fc26378e7b5081b80aade
local 3c60f74d1f9989c23a87ab30d76eaebcc8d91515bad77bf93d0d8acd8948f1d4
・・・略・・・
またMySQLコンテナに入りファイルを作ろうとしても、スペースがないため作成できないエラーが出ていました。
$ docker-compose -f docker-compose.yml exec mysql bash
root@b62c2fa99375:/# dd if=/dev/zero of="sample_file.yml" bs=1 count=1
dd: error writing 'sample_file.yml': No space left on device
1+0 records in
0+0 records out
0 bytes copied, 0.0002786 s, 0.0 kB/s
そのため、不要なvolumeを削除することで解決できます。
$ docker volume rm 2a75c2409d8d2ef9c66d276e75bbd3d4338d6b77719378e17d4e992c4df132cc
2a75c2409d8d2ef9c66d276e75bbd3d4338d6b77719378e17d4e992c4df132cc
おわりに
この記事では、db:create時のMySQLエラーと原因をまとめました。
基本的なところですが、記事を書いて再確認できたので良かったと思います。
また、この現象を発生させるにあたり、dockerのvolumeを意図的に増やすこともできるようになったので良かったと思います。
この記事が誰かのお役に立てれば幸いです。
Discussion