LoginSignup
12
12

More than 5 years have passed since last update.

bindfs を使った MariaDB(MySQL) コンテナのデータ永続化(NFS編)

Posted at

通常、データベースのコンテナのデータ永続化には、データコンテナを使う方法がよく知られていますが、やはり外部のディスクをマウントしてそこに保存したくなります。

しかし、単純に NFS 等でマウントしたフォルダに対して直接データを保存しようとすると権限がらみでエラーを起こす場合があります。

例えば、Vagrant を使って↓こんな感じで MariaDB を起動しようと vagrant up すると、

(Vagrantfile から一部抜粋)

  config.vm.synced_folder "./mariadb", "/mariadb", type: "nfs"

  config.vm.provision :docker do |docker|
    docker.pull_images "mariadb"
    docker.run "mariadb",
      image: "mariadb",
      args: [
        "-e MYSQL_ROOT_PASSWORD=test",
        "-v /mariadb:/var/lib/mysql"
      ].join(" "),
      restart: false
  end
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
72c9a74e6fcc        mariadb             "/docker-entrypoint.s"   7 seconds ago       Exited (1) 6 seconds ago                       mariadb
$ docker logs mariadb
chown: changing ownership of '/var/lib/mysql/': Operation not permitted

と、なってしまいます。

では、まず一つ目の解決方法は、

Vagrant の NFS のオプションを使って、強制的にマウント先に root 権限を渡してしまう危険な方法。

  config.vm.synced_folder "./mariadb", "/mariadb", type: "nfs"

  config.nfs.map_uid = 0
  config.nfs.map_gid = 0

  config.vm.provision :docker do |docker|
    docker.pull_images "mariadb"
    docker.run "mariadb",
      image: "mariadb",
      args: [
        "-e MYSQL_ROOT_PASSWORD=test",
        "-v /mariadb:/var/lib/mysql"
      ].join(" "),
      restart: false
  end
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
90969077c350        mariadb             "/docker-entrypoint.s"   7 seconds ago       Up 6 seconds        3306/tcp            mariadb
$ ls -la /mariadb
total 110648
drwxr-xr-x   11 999      999            374 Apr 12 17:36 ./
drwxr-xr-x   17 root     root           420 Apr 12 17:35 ../
-rw-rw----    1 999      999          16384 Apr 12 17:36 aria_log.00000001
-rw-rw----    1 999      999             52 Apr 12 17:36 aria_log_control
-rw-rw----    1 999      999       50331648 Apr 12 17:36 ib_logfile0
-rw-rw----    1 999      999       50331648 Apr 12 17:36 ib_logfile1
-rw-rw----    1 999      999       12582912 Apr 12 17:36 ibdata1
-rw-rw----    1 999      999              0 Apr 12 17:36 multi-master.info
drwx------   89 999      999           3026 Apr 12 17:36 mysql/
drwx------    3 999      999            102 Apr 12 17:36 performance_schema/
-rw-rw----    1 root     999          24576 Apr 12 17:36 tc.log

まあ、動くには動くんですが、これはかなりまずいですね。
一部のフォルダとは言え、root 権限を export してしまうのは問題ありです。

そこで登場するのが bindfs

mount --bind と同様に既存のフォルダを別のフォルダにバインド(マウント)するのがお仕事なんですが、それと同時に、ファイル/フォルダのオーナーやグループ、パーミッションを変更、制御しつつ、マウントしてくれるのが特徴です。

以下のように、NFS で export されているローカルの UID/GID を mysql(999)/mysql(999) に map しつつ、/mariadb~/mariadb にマウントさせると、

UID=`id -u`.strip
GID=`id -g`.strip

  config.vm.synced_folder "./mariadb", "/mariadb", type: "nfs"

  config.vm.provision :shell do |sh|
    sh.inline = <<-EOT
      mkdir -p ~/mariadb
      bindfs --map=#{UID}/999:@#{GID}/@999 /mariadb ~/mariadb
    EOT
  end

  config.vm.provision :docker do |docker|
    docker.pull_images "mariadb"
    docker.run "mariadb",
      image: "mariadb",
      args: [
        "-e MYSQL_ROOT_PASSWORD=test",
        "-v ~/mariadb:/var/lib/mysql"
      ].join(" "),
      restart: false
  end
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
8f0c1fb44d73        mariadb             "/docker-entrypoint.s"   4 seconds ago       Up 3 seconds        3306/tcp            mariadb

うまくいきました!

$ ls -la /mariadb
total 110648
drwxr-xr-x   11 501      20             374 Apr 12 17:42 ./
drwxr-xr-x   17 root     root           420 Apr  9 17:42 ../
-rw-rw----    1 501      20           16384 Apr 12 17:42 aria_log.00000001
-rw-rw----    1 501      20              52 Apr 12 17:42 aria_log_control
-rw-rw----    1 501      20        50331648 Apr 12 17:42 ib_logfile0
-rw-rw----    1 501      20        50331648 Apr 12 17:42 ib_logfile1
-rw-rw----    1 501      20        12582912 Apr 12 17:42 ibdata1
-rw-rw----    1 501      20               0 Apr 12 17:42 multi-master.info
drwx------   89 501      20            3026 Apr 12 17:42 mysql/
drwx------    3 501      20             102 Apr 12 17:42 performance_schema/
-rw-rw----    1 501      20           24576 Apr 12 17:42 tc.log
$ sudo ls -la /root/mariadb
total 110648
drwxr-xr-x   11 999      999            374 Apr 12 17:42 .
drwx------    3 root     root            80 Apr 12 17:41 ..
-rw-rw----    1 999      999          16384 Apr 12 17:42 aria_log.00000001
-rw-rw----    1 999      999             52 Apr 12 17:42 aria_log_control
-rw-rw----    1 999      999       50331648 Apr 12 17:42 ib_logfile0
-rw-rw----    1 999      999       50331648 Apr 12 17:42 ib_logfile1
-rw-rw----    1 999      999       12582912 Apr 12 17:42 ibdata1
-rw-rw----    1 999      999              0 Apr 12 17:42 multi-master.info
drwx------   89 999      999           3026 Apr 12 17:42 mysql
drwx------    3 999      999            102 Apr 12 17:42 performance_schema
-rw-rw----    1 999      999          24576 Apr 12 17:42 tc.log

ls の出力で見られるように、NFS のマウント先ではローカルのオーナーに、
bindfs で作られたバインド先では、mysql(999) がオーナーになっているのがわかります。

これで、vagrant destroy しても、再度 vagrant up すれば、データはそのまま引き続き使うことが出来ます。

これ、wocker と一緒に使えないかなぁ。

ちなみに、完全な Vagrantfile はこちらです。
https://gist.github.com/ailispaw/4c90d9f2086ae388f998ed0c809e820c

12
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
12