Mac OSでMySQLのDockerイメージを使ったらVOLUMEに書き込み権限がなくなった

# 困ったことの概要
Mac OSでMySQLのDockerイメージを使ったのですが、VOLUMEに書き込み権限がなく起動に失敗しました。
解決策と原因を説明します。

## 検証環境
- Mac OS X El Capitan (10.11.3)
- docker-machine version 0.5.5, build 02c4254
- Docker version 1.9.1, build a34a1d5
- docker-compose version 1.5.2, build 7240ff3

## 同じ問題を議論しているGitHub上のIssue
同じ現象なので、英語が使える場合はこちらを読むだけで解決します：
[How to use host volume in OSX by docker-machine (boot2docker) · Issue #99 · docker-library/mysql] (https://github.com/docker-library/mysql/issues/99)

以下で述べる解決策で参考にしたコメント：
[hklindworth commented on 14 Jan](https://github.com/docker-library/mysql/issues/99#issuecomment-171439846)


# 現象の再現手順
以下のように`docker-compose.yml`を用意します：

```bash
kazuma$ pwd
/Users/kazuma/workspace/qiita
kazuma$ ls -Ap1
data/
docker-compose.yml
```

```yaml:docker-compose.yml
mysql:
    image: mysql:5.5.47
    environment:
        - MYSQL_ALLOW_EMPTY_PASSWORD=yes
    volumes:
        - ./data:/var/lib/mysql
```

MySQLコンテナ内の`/var/lib/mysql`を`./data`にマウントして、コンテナ内のデータをホスト上に取得しようとしています。
取得できた`./data`を持ち運べば、他のMySQLコンテナでDBデータを再現することができます。

しかし、この状態ではMySQLコンテナの起動ができません：

```bash
kazuma$ docker-compose up
Creating qiita_mysql_1
Attaching to qiita_mysql_1
mysql_1 | 160326  8:21:14 [Note] mysqld (mysqld 5.5.47) starting as process 1 ...
mysql_1 | 160326  8:21:14 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
mysql_1 | 160326  8:21:14 [Note] Plugin 'FEDERATED' is disabled.
mysql_1 | mysqld: Table 'mysql.plugin' doesn't exist
mysql_1 | 160326  8:21:14 [ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
mysql_1 | 160326  8:21:14 InnoDB: The InnoDB memory heap is disabled
mysql_1 | 160326  8:21:14 InnoDB: Mutexes and rw_locks use GCC atomic builtins
mysql_1 | 160326  8:21:14 InnoDB: Compressed tables use zlib 1.2.3
mysql_1 | 160326  8:21:14 InnoDB: Using Linux native AIO
mysql_1 | 160326  8:21:14 InnoDB: Initializing buffer pool, size = 128.0M
mysql_1 | 160326  8:21:14 InnoDB: Completed initialization of buffer pool
mysql_1 | 160326  8:21:14  InnoDB: Operating system error number 13 in a file operation.
mysql_1 | InnoDB: The error means mysqld does not have the access rights to
mysql_1 | InnoDB: the directory.
mysql_1 | InnoDB: File name ./ibdata1
mysql_1 | InnoDB: File operation call: 'create'.
mysql_1 | InnoDB: Cannot continue operation.
qiita_mysql_1 exited with code 1
```

`The error means mysqld does not have the access rights to the directory.`とあります。
`/var/lib/mysql`に（書き込み）権限がなく、初期化に失敗しているようです。


# 解決策

以下のように`Dockerfile`を追加して、MySQLをrootで実行する設定に書き換えます：

```bash
kazuma$ pwd
/Users/kazuma/workspace/qiita
kazuma$ ls -Ap1
Dockerfile
data/
docker-compose.yml
```

```dockerfile:Dockerfile
FROM mysql:5.5.47

# MySQLをrootで実行する設定に書き換える
RUN sed -e 's/^ *user *= *mysql$/user = root/' -i /etc/mysql/my.cnf
```

`docker-compose.yml`も書き換え、`Dockerfile`を使うようにします：

```yaml:docker-compose.yml
mysql:
    # image: mysql:5.5.47
    build: .
    environment:
        - MYSQL_ALLOW_EMPTY_PASSWORD=yes
    volumes:
        - ./data:/var/lib/mysql
```

今度は無事に起動できました：

```bash
kazuma$ docker-compose up -d
Building mysql
Step 1 : FROM mysql:5.5.47
 ---> 36034fbee404
Step 2 : RUN sed -e 's/^ *user *= *mysql$/user = root/' -i /etc/mysql/my.cnf
 ---> Running in 70e1649baaa6
 ---> 1ef46053d80c
Removing intermediate container 70e1649baaa6
Successfully built 1ef46053d80c
Creating qiita_mysql_1
kazuma$ docker-compose ps
    Name               Command          State    Ports   
--------------------------------------------------------
qiita_mysql_1   /entrypoint.sh mysqld   Up      3306/tcp 
```

期待通り、`./data`にデータが出力されています：

```bash
kazuma$ ls -Ap1 data/
e23b0ab7c084.pid
ib_logfile0
ib_logfile1
ibdata1
mysql/
performance_schema/
```


# 原因
コンテナ内の`/var/lib/mysql`をホストのディレクトリにマウントすることで、MySQLの初期化プロセスが書き込み権限を失うためです。
これはMac OS上でDocker Machineを使って生じるもので、Linuxマシンでは発生しないようです（[MySQLイメージのドキュメント](https://hub.docker.com/_/mysql/)にとくに記述がないところを見ると）。

## 書き込み権限がなくなるのはなぜ？
`/var/lib/mysql`をホストの`/Users/kazuma/workspace/qiita/data`にマウントしていますが、実は、この`data`フォルダー、正確にはローカルマシン上のフォルダーではありません。
Docker Machine上の（今回は`default`を利用したので、VirtualBox (VM)上の）フォルダーなのです。
VM上のファイルパスとローカルのそれが一致するのは、VirtualBoxが共有フォルダーとしてVM上の`/Users`とローカルの`/Users`をリンクしていたからです。

共有フォルダーのパーミッションには固定のUIDとGIDが割り振られ、VirtualBox側の設定でしか変更できないようです。
MySQLプロセスのユーザー`mysql`では書き込み権限がなかったのはこのためです。
この記事での解決策は、MySQLを`root`で実行することにより、パーミッションの問題を回避するというものです。


# まとめ
ここで説明したものは、あまりスマートな解決策ではないような気がします（root使っていいんか？と思う）。
が、とりあえず回避するには使えるのでは。


# 参考リンク一覧
- [How to use host volume in OSX by docker-machine (boot2docker) · Issue #99 · docker-library/mysql](https://github.com/docker-library/mysql/issues/99)
    - [hklindworth commented on 14 Jan](https://github.com/docker-library/mysql/issues/99#issuecomment-171439846)
- [DockerのVolumeのアクセス権限の問題について - Qiita](http://qiita.com/mrk_21/items/137b0c39e09c3ed6c95a)