DockerでMySQL

この記事はMySQLのリファレンスから要所をメモ及び、コマンドの実施結果のメモです。
dev.mysql.com

目次

MySQLサーバーをたてる

utf8mb4をデフォルトの文字セットとして、utf8mb4_colをデータベースのデフォルトの照合順序として使用してMySQLのサーバーを起動する。

# docker run --name {コンテナの名前} -d {イメージの名前:tag} --character-set-server={デフォルトの文字セット} --collation-server={データベースのデフォルトの照合順序}
docker run --name mysql1 -d mysql/mysql-server:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_col

永続化

コンテナが削除されると、コンテナ内のMySQLに入っているデータや構成も同時に消失します。
これを防ぐためにホスト側のストレージとコンテナ内のボリュームをバインドします。

まずコンテナ内のボリュームがまだマウントされていないことを確認します。

$ docker inspect mysql1
[
    {
        ...
        "Mounts": [],
        ...
    }
]

次に/path-on-host-machine/my.cnfを作成します。
これはMySQLの構成を定義します。
本来なら詳細に定義しておくものですが、ここでは練習なのでホスト側のPCにあるものがコンテナ内のMySQLにマウントされていることが確認できればよいとします。

[mysqld]
user=mysql

また、MySQLのデータを置く場所として/path-on-host-machine/datadirを作成します。

mkdir /path-on-host-machine/datadir
docker run --nam=mysql1 \
--mount type=bind,src=/path-on-host-machine/my.cnf,dst=/etc/my.cnf \
--mount type=bind,src=/path-on-host-machine/datadir,dst=/var/lib/mysql \
-d mysql/mysql-server:tag

すると下記のようにマウントされるようになります。

...
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/home/gesogeso/src/article-docker-mysql/my.cnf",
                "Destination": "/etc/my.cnf",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "bind",
                "Source": "/home/gesogeso/src/article-docker-mysql/datadir",
                "Destination": "/var/lib/mysql",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
...

追加スクリプト

コンテナ作成直後にデータベースで実行する.shまたは.sqlスクリプトがある場合はそれをホストディレクトリに配置してから、そのディレクトリをコンテナ内の/docker-entrypoint-initdb.d/にマウントできる。

まずホスト側に起動後に作成するスクリプトを作る。

mkdir scripts
touch scripts/init.sql
echo "CREATE DATABASE IF NOT EXISTS sample_db" >> scripts/init.sql

コンテナを起動する。

docker run --name=mysql1 \
--mount type=bind,src=/path-on-host-machine/scripts/,dst=/docker-entrypoint-initdb.d/ \
-d mysql/mysql-server:tag

別のDockerコンテナ内のアプリケーションからMySQLへ接続する

Dockerネットワークを設定すると、別のDockerコンテナ内のクライアントアプリケーションがサーバーコンテナ内のMySQL Serverにアクセスできるように、複数のDockerコンテナが相互に通信できるようになる。

まずDockerネットワークを作成する。

docker network create my-custom-net

MySQLコンテナを作成

docker run --name=mysql1 --network=my-custom-net -d mysql/mysql-server

MySQLに接続するためのアプリケーションコンテナを起動

docker run --name=myapp1 --network=my-custom-net -d myapp

myapp1でmysqlコマンドを実行する。

docker exec -it myapp1 mysql --host=mysql1 --user=myuser --password

Enterprise Backupの使用

MySQL Enterprise Backupを用いるとインスタンスに対して複数のバックアップ方式を採用できる。
www.mysql.com

インスタンスを起動する。

docker run --name=mysqlserver \
--mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \
-d mysql/enterprise-server:8.0

MySQL Enterprise Editionイメージを使用してコンテナを起動し、MySQL Enterprise Backupコマンドmysqlbackupでインスタンスをバックアップする。

docker run \
--mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \
--mount type=bind,src=/path-on-host-machine/backups/,dst=/data/backups \
--rm mysql/enterprise-server:8.0 \
mysqlbackup -umysqlbackup -ppassword --backup-dir=/tmp/backup-tmp --with-timestamp \
--backup-image=/data/backups/db.mbi backup-to-image

ホストにバックアップファイルが存在していることがわかる。

$ ls /tmp/backups
db.mbi

コンテナを停止する。

docker stop mysqlserver

ホストでMySQLデータディレクトリのbindマウント内のすべての内容を削除する。

rm -rf /path-on-host-machine/datadir/*

MySQL Enterprise Editionイメージを使用してコンテナを起動し、MySQL Enterprise Backupコマンドcopy-back-and-apply-logを使用してリストアを実行すうr。
バックアップのサーバーデータディレクトリとストレージフォルダをバインド/マウントする。

docker run \
--mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \
--mount type=bind,src=/path-on-host-machine/backups/,dst=/data/backups \
--rm mysql/enterprise-server:8.0 \
mysqlbackup --backup-dir=/tmp/backup-tmp --with-timestamp \
--datadir=/var/lib/mysql --backup-image=/data/backups/db.mbi copy-back-and-apply-log

コンテナを再起動すると、リストアの結果を見ることができる。

docker restart mysqlserver

または、リストアされたデータディレクトリで新しいMySQL Serverを起動してもリストアの結果を確認できる。

docker run --name=mysqlserver2 \
--mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \
-d mysql/enterprise-server:8.0