困ったことの概要
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
現象の再現手順
以下のようにdocker-compose.yml
を用意します:
kazuma$ pwd
/Users/kazuma/workspace/qiita
kazuma$ ls -Ap1
data/
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コンテナの起動ができません:
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で実行する設定に書き換えます:
kazuma$ pwd
/Users/kazuma/workspace/qiita
kazuma$ ls -Ap1
Dockerfile
data/
docker-compose.yml
FROM mysql:5.5.47
# MySQLをrootで実行する設定に書き換える
RUN sed -e 's/^ *user *= *mysql$/user = root/' -i /etc/mysql/my.cnf
docker-compose.yml
も書き換え、Dockerfile
を使うようにします:
mysql:
# image: mysql:5.5.47
build: .
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
volumes:
- ./data:/var/lib/mysql
今度は無事に起動できました:
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
にデータが出力されています:
kazuma$ ls -Ap1 data/
e23b0ab7c084.pid
ib_logfile0
ib_logfile1
ibdata1
mysql/
performance_schema/
原因
コンテナ内の/var/lib/mysql
をホストのディレクトリにマウントすることで、MySQLの初期化プロセスが書き込み権限を失うためです。
これはMac OS上でDocker Machineを使って生じるもので、Linuxマシンでは発生しないようです(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使っていいんか?と思う)。
が、とりあえず回避するには使えるのでは。