はじめに
開発学習用のメモとして投稿します。
dockerで、MySQL8.0のコンテナを立ち上げる際に、次のデータベース初期化処理を自動的に行う設定を行いました。
- データベースの構築
- テーブルの構築
- サンプルデータのインポート
その際、3のサンプルデータのインポートで詰まったので、どのように解決したかについて書いていきます。
データベース初期化の方針
dockerのMySQLイメージでは、コンテナ内の/docker-entrypoint-initdb.dというディレクトリに、拡張子が.sh、.sql、.sql.gz、.sql.gzのデータベース初期化用のファイルを配置すると、コンテナを起動した時に実行してくれます。そこで、データベース初期化は次のように行うことにしました。
- データベースの構築、テーブルの構築、サンプルデータのインポートを行う.sqlファイルを用意し、コンテナ上の/docker-entrypoint-initdb.dにマウントする。実行順序はファイル名によるため、次のようなファイルを用意する。
- 01_create_database.sql
- 02_create_table.sql
- 03_load_data_infile.sql
- サンプルデータのcsvファイルを用意し、コンテナ上で、ファイルの読み取り、書き込みが許可されるディレクトリにマウントする。なお、ファイルの読み取り、書き込みが許可されるディレクトリは、secure-file-priv変数で設定できる。
問題点
上記方針のもと必要なファイルを用意し、docker compose up
コマンドで、コンテナを立ち上げて、MySQLに接続してみると、サンプルデータが入っていませんでした。。
試したこと
データベース、テーブルは存在していたので、01_create_database.sql、02_create_table.sqlに問題があるわけではなさそうです。
とりあえず、MySQLに接続し、03_load_data_infile.sqlに記載していたクエリを実行すると、次のエラーが返ってきました。
ERROR 1148 (42000): The used command is not allowed with this MySQL version
原因
エラー内容でググってみると、local_infileの設定が無効になっていたことが原因でした。MySQL8.0でLOAD DATA INFILE
ステートメントを使用するには、サーバー側とクライアント側の両方でlocal_infileを有効にする必要があるとのことです。
解決策
local_infileを有効とするには、シェルスクリプトを用意して、/docker-entrypoint-initdb.dにマウントしても実現できそうでしたが、my.cnfファイルに設定を記述する方が簡単そうだったので、次のようなmy.cnfを用意してコンテナ上の/etc/mysql/my.cnfにマウントすることにしました。
[mysql]
local-infile=1
[mysqld]
local-infile=1
再度やり直してコンテナを立ち上げると、サンプルデータがインポートされていました!
参考にした記事