MroongaのDockerコンテナーでのdatadirの使い方いろいろ
mysql mroonga

MroongaのDockerコンテナーでのdatadirの使い方いろいろ

このエントリーをはてなブックマークに追加

メリークリスマス! DBAです。

この記事は  Groonga Advent Calendar 2015 の25日目の記事です。

1日目の  MySQLで日本語全文検索ができるMroongaのDockerリポジトリーをメンテナンスしています 、8日目の  MroongaのDockerイメージをメンテナンスする、とは に続き、Mroonga + Docker第3弾です。

groonga/mroonga のDockerイメージでは、現在3通りのdatadirの扱い方をサポートしています。

  1. コンテナーの/var/lib/mysqlをコンテナーの中だけで使う
  2. コンテナーの/var/lib/mysqlをホストにマウントして使う
  3. ホストの(Mroongaのインストール済みの)datadirをコンテナーの/var/lib/mysqlにマウントして使う

まず、MroongaのDockerコンテナーではビルド時に「すぐに使い始められるような」状態に/var/lib/mysqlをセットアップしています。

具体的には、

  • root@% ユーザーをパスワードなしで作ります
  • Mroongaのinstall.sqlを実行します(INSTALL PLUGINと各種UDFのCREATE FUNCTIONが走ります)

の2つをやっています。MySQL 5.7になってちょっと細工が必要になっています が、そのあたりは こんな風 に細工してあります。

コンテナーのビルド時にdatadirがセットアップ済みなので、1. の使い方は非常に簡単で、docker runすればいいだけです。この場合、datadirは使い捨て(コンテナーをrmすると消える)になります。

それに対して 2. の方法では、「セットアップされていない(であろう)/var/lib/mysql」がマウントされるため、Mroongaのインストールやroot@%の作成を後付けで行わなくてはなりません。

というわけで それに対応したコミットがこちら です。/var/lib/mysql/ibdata1が存在しなければ、初期化されてないdatadirだとみなして、service mysqld start(この中でmysql_install_dbやmysqld --initializeが流れる)と、イメージビルドの時点でコピーしておいたmysql-community-mroongaのpost-installスクリプトを流し、さらにroot@%を作ります。

$ sudo docker run -d -v /home/yoku0825/mroonga:/var/lib/mysql groonga/mroonga
04d4a69f0321d15d55edd1dc73c0f9607314f0e18a966837511588d66c7aa358

$ sudo docker logs 04d4a69f0321d15d55edd1dc73c0f9607314f0e18a966837511588d66c7aa358
..
Initializing MySQL database:
..
[  OK  ]
Starting mysqld:  [  OK  ]
/usr/bin/mysql -u root < /usr/share/mroonga/install.sql
Stopping mysqld:  [  OK  ]
Starting mysqld:  [  OK  ]
Stopping mysqld:  [  OK  ]
..
Version: '5.6.27'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MySQL Community Server (GPL)

このとおり、docker logsでdatadirが初期化され、install.sqlが実行されているのを見ることができます。

$ ls -l mroonga/
total 110612
-rw-rw---- 1 mysql mysql        4 Dec 24 11:48 04d4a69f0321.pid
-rw-rw---- 1 mysql mysql       56 Dec 24 11:48 auto.cnf
-rw-rw---- 1 mysql mysql      576 Dec 24 11:48 groonga.log
-rw-rw---- 1 mysql mysql 12582912 Dec 24 11:48 ibdata1
-rw-rw---- 1 mysql mysql 50331648 Dec 24 11:48 ib_logfile0
-rw-rw---- 1 mysql mysql 50331648 Dec 24 11:48 ib_logfile1
drwx------ 2 mysql mysql     4096 Dec 24 11:48 mysql
srwxrwxrwx 1 mysql mysql        0 Dec 24 11:48 mysql.sock
drwx------ 2 mysql mysql     4096 Dec 24 11:48 performance_schema

ホストから参照することも可能です。この方法でホスト上にdatadirを固定化しておけば、Dockerコンテナーを破棄してもdatadirは失われないためこれを利用して 3. の方法で使いまわすことができます。

3. の方法なんて本当は大したことはないのですが、1つだけ問題があります。上記 2.でホスト上に作成したdatadirを使い回すには問題ないのですが、それ以外の方法で「どこか(たとえば、ホスト上のMySQLとか)で作ったdatadir」を使い回す場合、パーミッションの問題が発生することがあるのです。

Mroongaのイメージ上では、mysqlユーザーのUIDは27で固定されています(これはmysql-community-serverのpost-installスクリプトにハードコードされています)そのため、datadirのオーナーはUID 27でなければなりませんが、これはホスト側の設定に依存します。

というわけで、3. の方法で起動された場合、コンテナーの中から見てオーナーがmysqlユーザーになるようにchownをかけて、mysqldの終了後に元のオーナーにchownで戻す処理が entrypoint.sh に入っています。

$ sudo chown -R yoku0825. /home/yoku0825/mroonga
$ ls -l /home/yoku0825/mroonga/
total 110612
-rw-rw---- 1 yoku0825 yoku0825        4 Dec 24 11:48 04d4a69f0321.pid
-rw-rw---- 1 yoku0825 yoku0825       56 Dec 24 11:48 auto.cnf
-rw-rw---- 1 yoku0825 yoku0825      804 Dec 24 12:06 groonga.log
-rw-rw---- 1 yoku0825 yoku0825 12582912 Dec 24 12:06 ibdata1
-rw-rw---- 1 yoku0825 yoku0825 50331648 Dec 24 12:06 ib_logfile0
-rw-rw---- 1 yoku0825 yoku0825 50331648 Dec 24 11:48 ib_logfile1
drwx------ 2 yoku0825 yoku0825     4096 Dec 24 11:48 mysql
drwx------ 2 yoku0825 yoku0825     4096 Dec 24 11:48 performance_schema

$ sudo docker run -d -v /home/yoku0825/mroonga:/var/lib/mysql groonga/mroonga
0c35fe26c14393bc8bbea17c468ae31baafd78b6d6d442b2ed6ed31bdfad2984

$ ls -l /home/yoku0825/mroonga/
total 110616
-rw-rw---- 1 27 27        4 Dec 24 11:48 04d4a69f0321.pid
-rw-rw---- 1 27 27        3 Dec 24 12:07 0c35fe26c143.pid
-rw-rw---- 1 27 27       56 Dec 24 11:48 auto.cnf
-rw-rw---- 1 27 27      924 Dec 24 12:07 groonga.log
-rw-rw---- 1 27 27 12582912 Dec 24 12:07 ibdata1
-rw-rw---- 1 27 27 50331648 Dec 24 12:07 ib_logfile0
-rw-rw---- 1 27 27 50331648 Dec 24 11:48 ib_logfile1
drwx------ 2 27 27     4096 Dec 24 11:48 mysql
srwxrwxrwx 1 27 27        0 Dec 24 12:07 mysql.sock
drwx------ 2 27 27     4096 Dec 24 11:48 performance_schema

$ mysqladmin -h 172.17.0.95 shutdown

$ ls -l /home/yoku0825/mroonga/
total 110612
-rw-rw---- 1 yoku0825 yoku0825        4 Dec 24 11:48 04d4a69f0321.pid
-rw-rw---- 1 yoku0825 yoku0825       56 Dec 24 11:48 auto.cnf
-rw-rw---- 1 yoku0825 yoku0825     1032 Dec 24 12:09 groonga.log
-rw-rw---- 1 yoku0825 yoku0825 12582912 Dec 24 12:09 ibdata1
-rw-rw---- 1 yoku0825 yoku0825 50331648 Dec 24 12:09 ib_logfile0
-rw-rw---- 1 yoku0825 yoku0825 50331648 Dec 24 11:48 ib_logfile1
drwx------ 2 yoku0825 yoku0825     4096 Dec 24 11:48 mysql
drwx------ 2 yoku0825 yoku0825     4096 Dec 24 11:48 performance_schema

ここでひとつ注意しないといけないのは、docker stopでコンテナーを停止させてしまうと オーナーは元に戻らない ことです。あくまでentrypoint.shの中でmysqldが終了した後に記述してあるコマンドで元に戻しているので、entrypoint.shをそのまま停止してしまうdocker stopではオーナーはUID 27のままになります。なので、mysqladmin shutdownで停止してあげてください。

Mroongaを利用したアプリの単体テストなどにご利用ください。

それでは良いお年を!


名無しのエンジニア
MroongaのDockerイメージをメンテナンスする、とは
16年間うごいているWebアプリケーションが抱えていた技術的負い目を考察する