症状
Docker コンテナ内でボリュームマウントしたディレクトリにアクセスすると permission denied エラーが発生する。
結論:まずこれを確認
- ホスト側のディレクトリ/ファイルの所有者・パーミッションを確認する
- コンテナ内で実行しているユーザーの UID/GID を確認する
- SELinux/AppArmor が有効な環境では
:zまたは:Zオプションを試す
トラブルシューティングフロー
flowchart TD
A[permission denied 発生] --> B{ホスト側の<br>パーミッションは?}
B -->|読み取り不可| C[chmod/chown で修正]
B -->|問題なし| D{コンテナの<br>実行ユーザーは?}
D -->|root| E{SELinux/AppArmor<br>有効?}
D -->|非root| F[UID/GID 不一致を確認]
E -->|Yes| G[:z オプションを追加]
E -->|No| H[Docker Desktop の<br>ファイル共有設定を確認]
F --> I[--user オプションで<br>UID を指定]
C --> J[再度アクセス確認]
G --> J
H --> J
I --> J
よくある原因
- ホスト側のパーミッション不足 - マウント元のディレクトリ/ファイルに適切な権限がない
- UID/GID の不一致 - コンテナ内ユーザーとホスト側ファイルの所有者が異なる
- SELinux のラベル問題 - SELinux 有効環境でコンテキストラベルが付与されていない
- AppArmor の制限 - AppArmor プロファイルがアクセスを拒否している
- Docker Desktop のファイル共有設定 - 共有対象ディレクトリに含まれていない(Mac/Windows)
- 読み取り専用マウント -
:roオプションで書き込みが制限されている - 名前付きボリュームの初期化問題 - ボリューム作成時の所有者が異なる
確認手順
ステップ1: エラーメッセージを確認する
# コンテナのログを確認
docker logs <container_name>
# コンテナ内でコマンド実行時のエラーを確認
docker exec -it <container_name> ls -la /path/to/mount
🔍 チェックポイント: Permission denied の対象がファイルかディレクトリか、読み取りか書き込みかを特定する
ステップ2: ホスト側のパーミッションを確認する
# マウント元のパーミッションを確認
ls -la /host/path/to/directory
# 所有者とグループを確認
stat /host/path/to/directory
🔍 チェックポイント: 出力例 drwxr-xr-x 2 user user - 所有者以外は書き込み不可
ステップ3: コンテナ内の実行ユーザーを確認する
# コンテナ内のユーザーID を確認
docker exec -it <container_name> id
# 出力例: uid=1000(appuser) gid=1000(appuser) groups=1000(appuser)
🔍 チェックポイント: ホスト側ファイルの所有者 UID とコンテナ内ユーザーの UID が一致しているか
ステップ4: UID/GID を一致させる
方法A: コンテナ起動時にユーザーを指定
# ホスト側ユーザーの UID で実行
docker run --user $(id -u):$(id -g) -v /host/path:/container/path image_name
方法B: ホスト側のパーミッションを変更
# 誰でも読み書き可能にする(セキュリティリスクあり)
chmod -R 777 /host/path/to/directory
# または特定ユーザーに所有権を変更
sudo chown -R 1000:1000 /host/path/to/directory
🔍 チェックポイント: docker exec -it <container_name> touch /path/to/mount/test でファイル作成できれば成功
ステップ5: SELinux 環境での対処
# SELinux の状態を確認
getenforce
# ボリュームマウント時に :z オプションを追加
docker run -v /host/path:/container/path:z image_name
# 複数コンテナで共有する場合は :Z(大文字)
docker run -v /host/path:/container/path:Z image_name
🔍 チェックポイント: Enforcing と表示される場合は SELinux が有効
ステップ6: Docker Desktop の設定を確認する(Mac/Windows)
Mac の場合:
- Docker Desktop → Settings → Resources → File Sharing
- マウントしたいディレクトリが一覧に含まれているか確認
- 含まれていない場合は追加して Apply & Restart
🔍 チェックポイント: /Users、/Volumes、/tmp などはデフォルトで共有対象
NG行動(やってはいけないこと)
chmod 777を本番環境で使う - セキュリティリスクが高い。開発環境での一時的な確認のみに留める- コンテナを常に root で実行する - セキュリティ上推奨されない。必要最小限の権限で実行する
- SELinux を無効化する - システム全体のセキュリティが低下する。
:zオプションで対処する - 原因特定せずに
sudoを多用する - 根本原因が隠れて再発する
よくある質問(FAQ)
Q1: Docker Compose の場合はどうする?
A: volumes セクションで同様に :z オプションを指定できる。user ディレクティブで UID を指定することも可能。
services:
app:
image: myapp
user: "1000:1000"
volumes:
- ./data:/app/data:z
Q2: 名前付きボリュームでも同じ症状が出る?
A: 出る場合がある。名前付きボリュームはコンテナ初回起動時に作成され、その時のユーザーが所有者になる。docker volume inspect <volume_name> で Mountpoint を確認し、ホスト側から所有者を変更する。
Q3: WSL2 環境で発生する場合は?
A: WSL2 と Windows 間のファイルシステム変換が原因の場合がある。/mnt/c/ 配下ではなく WSL2 内のファイルシステム(/home/ など)を使用すると改善することがある。
関連するエラー・症状
- (関連記事準備中)
- (関連記事準備中)
- (関連記事準備中)
解決しない場合
公式ドキュメント
確認すべきログファイル
# Docker デーモンのログ(Linux)
journalctl -u docker.service
# コンテナのログ
docker logs --tail 100 <container_name>
# SELinux の拒否ログ
sudo ausearch -m avc -ts recent
次に調べるキーワード
docker volume uid giddocker userns-remapselinux docker contextdocker rootless mode permission