docker-compose.yml を用いたコンテナ起動時の Volume の権限エラーの解説・解決方法
【Docker】 コンテナが Permission denied で起動しない時の対処法と仕組み
MySQLデータベースのコンテナ構築をすると、権限設定のエラーが発生したので、解決策とその原因を備忘録です。
同じエラーに遭遇した方の助けになれば幸いです。
使用技術
- M3 MacBook
- Rancher Desktop
🚨 発生したエラー
以下の docker-compose.yml を書き、コンテナを立ち上げようと docker compose up -d を叩いたところ、コンテナがすぐに終了(Exited)してしまいました。
以下のコマンドでログを確認すると、以下のエラーが出ていました。
$ docker logs <container_id>
[Entrypoint]: Entrypoint script for MySQL Server 8.0 started.
chown: changing ownership of '/var/lib/mysql/': Permission denied
chown: changing ownership of '/var/lib/mysql': Permission denied
原因は?
Permission Denied つまり、権限がないことはわかりました。
chown: changing ownership of '/var/lib/mysql/': Permission denied
ログに記載されているこの chown コマンドは、ファイルやディレクトリの所有権を変更するコマンドです。
MySQLコンテナは、この chown コマンドを使い、起動時にデータ保存先フォルダの所有者を自分(mysqlユーザー)に変更しようとします。
ただ、ホスト(Mac)側も、勝手に所有権を変えられるほどヤワではありません。
ホストのファイルシステムが、「勝手に所有権を変えないで!」と、ブロックします。
ここで、解決策は大きく分けて2つあります。
1. ホストのユーザーIDと、コンテナのユーザーIDを同じにする
2. Named Volume を使い、そもそも権限問題を発生させないようにする
何をいってるの? と思うかもしれませんが、一旦みていきましょう。
1番の「ホストのユーザーIDと、コンテナのユーザーIDを同じにする」については、こちらの記事で解説されているので、割愛しようと思います。
もっと手軽に行える2番の記事について、今回は深掘りして解説します。
✅ 解決策:Named Volume を使う
まず、結論から。
ローカルのフォルダを直接マウントする(Bind Mount)のをやめ、Dockerの「Named Volume(名前付きボリューム)」 を使う構成に変えることで解決しました。
❌ うまくいかなかった設定 (Bind Mount)
ローカルの ./mysql_data フォルダを直接コンテナに見せる設定です。
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
# ...省略
volumes:
# 👇 ここが原因(Macのフォルダを直接指定している)
- ./mysql_data:/var/lib/mysql
⭕️ 解決した設定 (Named Volume)
Docker管理下のボリューム領域を使う設定に変更します。
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
# ...省略
volumes:
# 👇 パスではなく「名前」を指定する
- db_data:/var/lib/mysql
# 👇 ファイルの末尾にボリューム定義を追加
volumes:
db_data:
一旦コンテナを削除し、再起動します。
docker compose down
以前のエラーで作成されたフォルダがあれば削除(紛らわしいので)
rm -rf mysql_data
再起動
docker compose up -d
これで無事、MySQLが起動しました!🎉
なぜこれで解決するのか? (仕組みの解説)
「なぜフォルダ指定だとダメで、ボリュームだとOKなのか?」 ここが直感的に分かりにくかったので、前提から仕組みを整理します。
Docker の構造
Docker の仕組みとして、よく取り上げられるのはこんな感じの図だと思います。
Dockerコンテナは、ホストOS の「カーネル」というものを使います。
まぁ、OSの「核」というイメージですね。
でもこれ、なんのカーネルでもいいわけではなく、「Linux OSのカーネル」を期待しているんです。
MacOSのカーネルは、「Linux OS のカーネル」とは違うので、Mac上で動くDockerコンテナは、macOS 上に Linux仮想マシン (Linux VM) を欲しています。
そこで、Rancher Desktop (Docker Desktop)は、裏で Linux 仮想マシンを立ち上げているのです。
そして、その Linux 仮想マシンの上でコンテナが作動しているんですね。

1. ❌ Bind Mount(フォルダ指定) の場合
これは、「Macのフォルダ」をコンテナに貸し出す 状態です。
OSには ユーザー という概念があり、各操作はユーザーによって行われます。
そして、各ユーザーには ユーザーID と 権限 が割り当てられています。
MySQL: 「データの所有者を ID:999(コンテナ内のMySQLユーザー)に書き換えたい!」
Mac: 「ダメ。ここはMacのファイルシステム(APFS)だ。ID:501(Macのユーザー)のもの!」
結果、 Macのセキュリティが働き、「部外者が勝手に所有権を変えるな」 と chown をブロックします。

✅ Named Volume(ボリューム指定)の場合
これは、「Linux VMの中にあるDocker専用倉庫」にデータを置く 状態です。
場所: データの実体はMac上のフォルダとして直接見える場所ではなく、Linux VM の中(仮想ディスク内) に作られます。
結果: MySQL が chown を実行しても、そこは Linux のテリトリーなので、Linux のルール通りに所有権の変更が許可されます。
つまり、Volume を ホストOS ではなく、Linux の管理下におくことで、権限問題を解決しているのです。

【補足】 docker compose down したら volume のデータは消えないの?
先ほどの説明で、
「VolumeがDockerの管理領域にある」と聞くと、コンテナを消したらデータも消えそうな気がしなくもないのですが、そこは問題ないです。
コンテナ (docker compose down) = データ処理等を行う実体
ボリューム (db_data) = データ保管倉庫
処理する実体を壊しても、倉庫は地面(VM)に残ります。
docker compose down でコンテナを削除しても、ボリュームは保持され続けます。
次に docker compose up した際、同じボリューム名を指定していれば、前回のデータを引き継いで起動します。
※ データを完全に消してやり直したい場合だけ、docker compose down -v(ボリュームも削除)を使えばOKです。
まとめ
Mac等の環境で MySQL の Permission denied が出たら、ファイル権限の衝突を疑う。
ホストのフォルダを直接マウントせず、Named Volume を使うと解決する。
Named Volume は Linux VM の中 にデータを持つため、権限周りのトラブルが起きにくい。
ボリューム内のデータは、コンテナを消しても永続化されるので安心。
Discussion