DockerでMySQLを使う

MySQLの公式Dockerイメージの基本的な使い方の紹介です。

Dockerでのファイルマウント方法、ネットワーク仕様については、Dockerまとめを参照してください。

コンソールでの操作はすべてWSL UbuntuのBash上のものです。

起動からmysqlコマンドでのDB操作まで

環境変数でパスワードを設定した状態で起動します。

$ docker run -d --rm --name temp-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw mysql:9.6.0

コンテナのシェルに入り、mysqlコマンドが実行できます。

$ docker exec -it temp-mysql bash
bash-5.1# mysql --version
mysql  Ver 9.6.0 for Linux on x86_64 (MySQL Community Server - GPL)
bash-5.1# mysql -u root -pmy-secret-pw
mysql> status
mysql> create database db1;
mysql> show databases;
mysql> exit
bash-5.1# exit

bash経由ではなく、直接mysqlコマンドでコンテナに入ることもできます。

$ docker exec -it temp-mysql mysql -u root -pmy-secret-pw

phpMyAdminから接続する

phpMyAdminの公式Dockerイメージを使います。

コンテナ同士で接続できるようにDockerのユーザー定義ネットワークを作成しておきます。

$ docker network create nw1

MySQLのコンテナに作成したネットワークを割り当てて起動します。

$ docker run -d --rm --name temp-mysql --network=nw1 -e MYSQL_ROOT_PASSWORD=my-secret-pw mysql:9.6.0

phpMyAdminの設定

  • MySQLコンテナと同じネットワークを割り当てます。
  • phpMyAdminの接続先DBコンテナの名称はdbにする必要があるため、linkオプションでtemp-mysqlにdbという別名を設定します(MySQLコンテナの名称を元からdbにした場合は、linkオプションの設定は不要です)。
  • ブラウザからアクセスできるようにポートを公開しておきます(今回は8080番使用)。
% docker run -d --rm --name phpmyad --network=nw1 --link temp-mysql:db -p 8080:80 phpmyadmin:5.2.3

http://localhost:8080/ にアクセスし、ユーザー名:root、パスワード:my-secret-pwでログインできます。

DBファイルのマウント

データベースを永続化するためにマウントしてみます。

DBファイルをローカル上に作成

カレントディレクトリに空のディレクトリmysqlを作成し起動することで、初回起動時に自動的にDBファイルが作成され、2回目以降は作成済みのDBファイルが読み込まれます。

エラーが出たときに分かりやすいように今回は-itのオプションを付けています。

$ mkdir mysql
$ docker run -it --rm --name temp-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw \
--mount type=bind,src="$(pwd)/mysql",dst=/var/lib/mysql mysql:9.6.0

DBファイルをDocker Volume上に作成

ボリュームが存在しない場合は最初に作成しておきます。

$ docker volume create vol-mysql

# 作成結果を確認
$ docker volume ls

mountのtypeをvolumeにし、srcに作成したvolume名を指定します。

$ docker run -it --rm --name temp-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw \
--mount type=volume,src=vol-mysql,dst=/var/lib/mysql mysql:9.6.0

設定ファイルの適用

コンテナの/etc/mysql/conf.dディレクトリをマウントすることで設定ファイルを適用することができます。

文字コードの設定

Windowsの場合、PowerShellでもWSL上でも、デフォルトの設定で起動するとクライアント側の文字コードセットがlatin1になるケースがあります。

この設定はmysqlのstatusコマンドやSHOW VARIABLES LIKE 'char%';コマンドで確認できます。

mysql> status
--------------
mysql  Ver 9.6.0 for Linux on x86_64 (MySQL Community Server - GPL)

Connection id:          9
Current database:
Current user:           root@localhost
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         9.6.0 MySQL Community Server - GPL
Protocol version:       10
Connection:             Localhost via UNIX socket
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    latin1
Conn.  characterset:    latin1
UNIX socket:            /var/run/mysqld/mysqld.sock
Binary data as:         Hexadecimal
Uptime:                 16 sec

Threads: 2  Questions: 6  Slow queries: 0  Opens: 119  Flush tables: 3  Open tables: 38  Queries per second avg: 0.375
--------------

この場合、私の環境では以下のケースで文字化けが起きました。

  • コンソールから日本語を含むデータを投入したとき
  • 文字エンコーディングがUTF8形式のSQLファイルを実行して、DBに日本語を含むデータを投入したとき

この文字化けを修正するためのcnfファイルを作成します。cnfディレクトリを作成し、その中にmy-config-file.cnfという名称で作成しました(拡張子がcnfであれば、ファイル名は任意で問題ないです)。

[client]
default-character-set=utf8mb4

cnfファイルは誰でも書き込み権限があると読み込まれないため、権限を644などに変更しておきます。WSLではなくWindows上のファイルで作成する場合は、ファイルのプロパティから読み取り専用の属性にチェックを入れてください(詳細は[Docker+Windows]mysqlのdockerイメージがmy.cnfのマウントのエラーで起動しない時の対処法 – Qiitaを参照)。

# cnfファイルの権限設定
$ chmod 644 cnf/my-config-file.cnf

# エラーメッセージが確認できるように-itオプション付けて起動
$ docker run -it --rm --name temp-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw \
--mount type=bind,src="$(pwd)/cnf",dst=/etc/mysql/conf.d \
mysql:9.6.0

別コンソールからコンテナに入り、文字コードの設定が変更されていることを確認します。

$ docker exec -it temp-mysql mysql -u root -pmy-secret-pw
mysql> status
--------------
~~~省略~~~
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
~~~省略~~~
--------------

DBの初期化処理

コンテナ上の/docker-entrypoint-initdb.dのディレクトリにshやsqlファイルを置いておけば、コンテナ初回起動時にアルファベット順にそれらが実行されます(ファイルを更新しても2回目以降の起動では実行されません)。

そのため、このディレクトリをマウントしておけば、ローカルファイルに置いたsqlコマンドを実行できます。

このsqlファイルでは、useコマンドなども末尾にセミコロンがないとエラーになるので注意してください。

以下の例では、mysql_initディレクトリをカレントディレクトリに作成し、そこに2つのSQLファイルを作成してみました。アルファベット順の実行なので、ゼロ埋め3桁の数字をプレフィックスに付けています。

001_create-db.sql
create database db1;
show databases;

use db1;
create table tb1(id varchar(10), name varchar(10), age int);
show tables;
desc tb1;
002_insert-data.sql
use db1;
insert into tb1 values('ID001', 'Alice', 10);
insert into tb1 (id, name, age) values
('ID002', 'Bob', 20),
('ID003', 'Corn', 30),
('ID004', '山田', 40)
;
select * from tb1;

文字化け対策用cnfファイルのマウントとphpMyAdminで確認するためのnetworkオプションも付けて起動します。ディレクトリは以下の構成です。

$ tree
.
├── cnf
│   └── my-config-file.cnf
└── mysql_init
    ├── 001_create-db.sql
    └── 002_insert-data.sql
$ docker run -it --rm --name temp-mysql --network=nw1 -e MYSQL_ROOT_PASSWORD=my-secret-pw \
--mount type=bind,src="$(pwd)/cnf",dst=/etc/mysql/conf.d \
--mount type=bind,src="$(pwd)/mysql_init",dst=/docker-entrypoint-initdb.d \
mysql:9.6.0

phpMyAdminのコンテナを起動し、DBが正常に作成されていることを確認できます。

phpMyAdminでの確認画像