Chapter04 Docker For MySQL

はじめに

ここではMySQLをコンテナで起動する方法をまとめておきます。SQLの練習だったろ、バージョンによる違いなどを検証する際にはDockerでMySQLのコンテナを作ることは非常に便利です。

MySQLコンテナの構築

MySQLコンテナを構築するには下記のコマンドを実行すれば、MySQLコンテナを起動できます。MySQLのイメージarrow-up-rightはDocker Hubから取得します。latestなので、MySQL8のイメージになります。ホスト側のポートの設定は、13306にしています。これは私のホストの実行環境で、MySQLを3306で使用しているためです。MYSQL_ROOT_PASSWORDはrootユーザーのパスワードです。

→ docker run -e MYSQL_ROOT_PASSWORD=pass -p 13306:3306 -d mysql:latest

Unable to find image 'mysql:latest' locally
latest: Pulling from library/mysql
8559a31e96f4: Pull complete 
d51ce1c2e575: Pull complete 
c2344adc4858: Pull complete 
fcf3ceff18fc: Pull complete 
16da0c38dc5b: Pull complete 
b905d1797e97: Pull complete 
4b50d1c6b05c: Pull complete 
c75914a65ca2: Pull complete 
1ae8042bdd09: Pull complete 
453ac13c00a3: Pull complete 
9e680cd72f08: Pull complete 
a6b5dc864b6c: Pull complete 
Digest: sha256:8b7b328a7ff6de46ef96bcf83af048cb00a1c86282bfca0cb119c84568b4caf6
Status: Downloaded newer image for mysql:latest
1c241beed989cc748631212e012743a217af1eb7495d2a1f9f6b61a22f59e351

MySQLのイメージからコンテナを構築する際には下記の環境変数を使用することが可能です。

環境変数名

内容

MYSQL_ROOT_PASSWORD

必須。MySQLのrootユーザーに設定されるパスワードを指定します。

MYSQL_DATABASE

オプション。イメージの起動時に作成されるデータベースの名前を指定できます。ユーザー/パスワードが指定されている場合、そのユーザーには、このデータベースへのGRANT ALL権限が付与されます。

MYSQL_USER, MYSQL_PASSWORD

オプション。新しいユーザーを作成し、そのユーザーのパスワードを設定します。このユーザーには、MYSQL_DATABASE変数で指定されたデータベースに対するroot権限が付与されます。ユーザーを作成するには、両方の変数が必要です。

MYSQL_ALLOW_EMPTY_PASSWORD

オプション。yes のような空でない値を設定すると、root ユーザの空白のパスワードでコンテナを起動することができます。

MYSQL_RANDOM_ROOT_PASSWORD

オプション。yes のような空でない値を設定すると、ルートユーザのためのランダムな初期パスワードを生成されます。

MYSQL_ONETIME_PASSWORD

rootユーザーをinitを完了した時点で期限切れになるように設定し、初回ログイン時にパスワードの変更を強制します。空でない値を指定すると、この設定が有効になります。

問題なく起動しているようなので、コンテナに入ってみます。

rootユーザーのパスワードを入力してMySQLにアクセスします。これでいつもどおりMySQLを利用できます。

MySQLコンテナのデータ

MySQLコンテナのデータは、コンテナを削除すると、もう一度コンテンを構築しても保存されていません。これを確認するために適当なデータベースとテーブルを作成し、値をインサートします。

一度、コンテナから抜けてコンテナに再度入ってみます。この状態では、コンテナを削除していないので、先程作成したデータベースとテーブルは残っています。

それではコンテナを削除して、再度、コンテナを起動します。

それでは新しいコンテナでMySQLにアクセスします。そうすると先程作成したデータベースとテーブルがなくなっておることが確認できます。

このようにコンテナを作り直すとデータは残りません。これを回避するには、ボリュームをマウントする必要があります。それを試す前に不要なコンテナを削除しておきます。

ホスト側のデスクトップにmysql_dataというディレクトリを作成します。ここをコンテナのMySQLのマウント先に設定します。

それではコンテナのMySQLにアクセスして、データベースとテーブルを作成して、

コンテナを削除します。

データベースとテーブルは作成して、デスクトップのmysql_dataディレクトリに保存しているので、これをコンテナを起動する際にマウントすれば先程の状態を再現できるはずです。中身はこのようになっています。

それではマウント先を指定して、コンテナを起動し、先程のデータがあるか確認すると、データベースとテーブルも残っており、データを確認できます。

MySQLコンテナにデフォルトでデータを格納する

MySQLコンテナを起動した際に、デフォルトでデータベースとテーブルが保存されている状態でコンテナを起動する方法をまとめます。これを実現するにはdocker-composeでコンテナを起動します。docker-composeについては、また別のチャプターで扱います。簡単に説明すると、コンテナを複数起動する場合などに、docker-compose.ymlに起動時の設定をまとめて記述しておき、そのファイルをもとにコンテナを起動できます。

まずは、デスクトップにmysql_dockerというディレクトリを作成し、そこに必要なファイルを保存していきます。

mysql_dockerというディレクトリの中身はこのようになっています。

起動時の設定をまとめて記述するdocker-compose.ymlの中身は下記の通りです。volumes./init:/docker-entrypoint-initdb.dの部分がポイントで、新しいコンテナが初めて起動されると、このマウント先のsql、shなどが実行され、その内容でコンテナが初期化されます。ここでは、init.sqlが実行されることになります。

init.sqlの中身は下記の通りです。データベースを作り、テーブルにデータをインサートします。データはデータサイエンス協会の前処理100本ノックの内容を一部お借りしています。

それではdocker-compose up -dを使ってコンテナを起動します。

それではテーブルにデータがインサートされているか確認します。問題なくデフォルトでデータが保存されていることがわかります。

データの保存先をホストのディレクトリにマウントしているので、テーブルにデータをインサートしたあとに、コンテナを削除して、先程と同じようにデータが残っているのか確認します。

では、もう一度コンテナを起動します。

コンテナが削除されてもデータが残っていることが確認できます。

MySQLコンテナのコンフィグファイルを設定する

MySQL のコンフィグファイルは /etc/mysql/my.cnf にあります。しかし、 /etc/mysql/conf.d/etc/mysql/mysql.conf.d のような追加のディレクトリが含まれている可能性があります。設定が一致していない場合、コンテナが起動しません。

コンフィグファイルを調整する場合、docker-compose.ymlにファイル先を記載します。ディレクトリ構造はこうなっています。

docker-compose.ymlは下記の通りです。

参考までにconfig-file.cnfは下記のとおりです。

この状態でコンテナを起動すればコンフィグファイルが反映されます。

補足:LOAD DATA LOCAL INFILEでインサートしたい場合

MySQLコンテナにデフォルトでデータを格納する方法は先程まとめましたが、そこそこ大きいデータをデフォルトでインサートしようとするとバルクインサートでも少し時間がかかります。そのような場合にはLOAD DATA LOCAL INFILEコマンドでインサートしたくなります。その方法をDockerで実現する方法について、ここではまとめておきます。

ファルダ構成は下記のとおりです。20_data_load.shLOAD DATA LOCAL INFILEコマンドを実行し、インサートしています。ここでは、test_dbの中のtest_tbl1test_tbl2に対して、data1.csvdata2.csvをコンテナ起動時にインサートするような流れを想定しています。

docker-compose.ymlに大きな変更はありません。

10_ddl.sqlの中身はこちらです。テーブルを作成するSQLの頭にset global local_infile = 1;を設定しています。MySQLの設定として、デフォルトでは、local_infileシステム変数がOFFなのでONにします。

20_data_load.shの中身はこちらです。クライアントから接続する際に--local-infile=1を指定してコマンドを実行します。

csvの中身はこちらです。

それではコンテナを立ち上げ、MySQLの中にアクセスします。

SQLを発行してデータがインサートされているか確認します。想定した通り、test_dbの中のtest_tbl1test_tbl2に対して、data1.csvdata2.csvがインサートされています。

Last updated