メモ > サーバ > 各論: Docker > データベースの永続化
データベースの永続化
マイグレーションやシーダーで管理するとオーバーヘッドが大きくなりすぎる
…という場合、データベースもファイル共有の対象にすればデータを保持できる
※後述の「トラブル代替案」ように、ファイル共有ではなくデータボリュームを使う方が良さそう
ファイル共有だと、環境によっては正しく動作しなかった
※docker-compose.ymlでrootパスワードなどを指定している場合、変更しても永続化済みのデータには影響しない
つまり「何故かパスワードの変更が反映されない」となるので注意
手動でパスワードなどを変更するか、永続化済みのデータを初期化するなどする
※データベースを永続化していると、MySQLコンテナが完全に起動するまでの時間が短くなっているかも?
諸々のデータ作成が短縮できるから…かもしれない
■docker container run の場合
※後述の「トラブル代替案」ように、ファイル共有ではなくデータボリュームを使う方が良さそう
ファイル共有だと、環境によっては正しく動作しなかった
-v $PWD/docker/test/data:/var/lib/mysql
を追加して起動する
/var/lib/mysql を同期すれば、MySQLのデータを保持できる
/docker/test/data フォルダはあらかじめ作成しておく
$ docker container run --net my_network --name mysql -v $PWD/docker/test/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=pass -e MYSQL_DATABASE=test -d mysql:5.7
$ docker container run --net my_network --name php -v $PWD/docker/test/code:/var/www/html -p 80:80 -d php:custom
■Docker Compose の場合
※後述の「トラブル代替案」ように、ファイル共有ではなくデータボリュームを使う方が良さそう
ファイル共有だと、環境によっては正しく動作しなかった
- ./database:/var/lib/mysql
を追加して起動する。意味は上と同じ
compose_test\docker-compose.yml
version: '3'
networks:
my_network:
services:
mysql:
container_name: mysql
volumes:
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
- ./docker/database:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: pass
MYSQL_DATABASE: test
networks:
- my_network
image: mysql:5.7
php:
container_name: php
volumes:
- ./:/var/www
ports:
- 80:80
networks:
- my_network
image: php:custom
■ボリュームの削除(データベースの削除)
$ docker volume ls ... ボリュームを確認
$ docker volume rm compose_mysql_data ... ボリュームを削除
■トラブル
2018/01/06 にWindowsアップデートするとDockerが起動しなくなった
再インストールで起動するようになったが、データベースの永続化ができないようになっていた
Composeを使う使わないにかかわらず永続化できず、MariaDBの場合でも同じ
「-d」なしで起動すると以下のようなエラーを確認できるが、原因不明のまま解決せず
Windows側で権限管理やファイルシステムの仕様が変更されたとか?
$ docker container run --name mysql -v $PWD/docker/test/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=pass -e MYSQL_DATABASE=test mysql:5.7
Initializing database
2018-01-06T17:47:41.143661Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2018-01-06T17:47:41.150773Z 0 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
2018-01-06T17:47:41.627330Z 0 [ERROR] InnoDB: Operating system error number 22 in a file operation.
2018-01-06T17:47:41.627674Z 0 [ERROR] InnoDB: Error number 22 means 'Invalid argument'
2018-01-06T17:47:41.628023Z 0 [ERROR] InnoDB: File ./ib_logfile101: 'aio write' returned OS error 122. Cannot continue operation
2018-01-06T17:47:41.628357Z 0 [ERROR] InnoDB: Cannot continue operation.
次の手段へ
データはbusyboxに保存するのが定番らしいので試す
$ docker container run --net my_network --name storage -v /var/lib/mysql -d busybox
$ docker container run --net my_network --name mysql --volumes-from storage -e MYSQL_ROOT_PASSWORD=pass -e MYSQL_DATABASE=test -d mysql:5.7
とすればmysqlのデータをbusyboxに保存できる
が、mysqlコンテナを再起動してもデータは消えないが、busyboxを再起動するとデータが消える
よってbusyboxからエクスポート&インポートする必要があるが、それだとmysqlをデータ同期無しで使っている状態と変わらない
次の手段へ
コンテナとローカルでデータ転送ができるらしいので試す
以下のようにすればデータ転送ができる
コンテナからローカルへ
$ docker container cp mysql:/var/lib/mysql /Users/refirio/docker/backup … 絶対パスの場合
$ docker container cp mysql:/var/lib/mysql ./docker/backup … 相対パスの場合
ローカルからコンテナへ
$ docker container cp /Users/refirio/docker/backup mysql:/var/lib/mysql … 絶対パスの場合
$ docker container cp ./docker/backup mysql:/var/lib/mysql … 相対パスの場合
が、ローカルからコンテナに転送すると所有者がrootになる。chownで所有者を変更してもmysqlからは読み込めなかった
権限なども調整が必要かも
非常に面倒なので、phpMyAdminのようなツールでエクスポート&インポートする方が現実的
つまりは実質、データベースは永続化せずに作業する状態となり、かなり面倒
■トラブル代替案
ホストの特定のパスではなく、データボリュームになら保存できた
むしろ、ファイルシステムや権限の問題を回避するためにも、データボリュームを使う方がいいみたい
データボリュームに保存したデータベースをバックアップしたければ、phpMyAdminなどのツールを使う
dockerコマンドから起動する場合(「mysql_data」に保存)
$ docker volume ls ... ボリュームを確認
$ docker volume create --name mysql_data ... 明示的に作成できるが省略可
$ docker container run --net my_network --name mysql -v mysql_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=pass -e MYSQL_DATABASE=test -d mysql:5.7
$ docker container exec -it mysql bash
$ mysql -u root -p
Docker Compose から起動する場合、以下のように指定する(「compose_mysql_data」に保存する場合)
services:
mysql:
container_name: mysql
volumes:
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
- compose_mysql_data:/var/lib/mysql
ボリュームの削除は以下のようにする
$ docker volume ls ... ボリュームを確認
$ docker volume rm compose_mysql_data ... ボリュームを削除
Dockerのデータ永続化関連について - Qiita
https://qiita.com/onokatio/items/fcc9f8f94f8533bb030a
dockerのデータボリュームとそのバックアップ方法 - Qiita
https://qiita.com/74th/items/41393f506d223850f2c3
Docker Data Volume を理解する - Carpe Diem
http://christina04.hatenablog.com/entry/2016/05/04/134323