1.はじめに
Laravelに限らずですが、Docker環境で開発していると以下のような権限トラブルに遭遇しがちです。
-
php artisan系のコマンドで動かないものがある -
storageの書き込み,閲覧ができない -
Permission deniedが頻発する
「ローカルでは動くのにDockerだと動かない」「突然ファイルに書き込めなくなった」 そのほとんどは権限問題です。
この記事では、よくあるケースとその原因・解決方法をまとめます。
前提知識: Dockerファイル権限の仕組み
コンテナ内のプロセスはデフォルトでrootとして動く
DockerfileでUSERを指定しない場合、コンテナ内のプロセスはUID 0(root)で実行されます。
この状態でファイルを作成すると、ホスト側でもroot所有のファイルになります。
ボリュームマウントとUID
DockerのボリュームマウントはUIDベースでファイル権限を管理します。ユーザ名ではなくUIDで一致判定されるため、ホスト側のUID 1000とコンテナ側のUID 1000は、ユーザ名が異なっていても同じユーザとして扱われます。
ホスト: youarname(UID=1000)が所有するファイル
コンテナ: appuser(UID=1000)が所有するファイルとして見える
→UIDが同じなので読み書き可能
解決方法
先に権限問題に対する解決方法をお伝えすると以下の方法になります。
方法A: UID/GIDをホストと一致させる(推奨)
ARG UID=1000
ARG GID=1000
RUN groupadd -g ${GID} appgroup \
&& useradd -u ${UID} -g ${GID} -m appuser
backend:
build:
context: ./docker/backend
args:
UID: ${UID}
GID: ${GID}
user: "${UID}:${GID}"
volumes:
- ./backend:/var/www
方法B: ホスト側でディレクトリの権限を変更する
chmod -R 775 backend/storage backend/bootstrap/cache
方法Bは手軽なのですが、チーム開発では全員が同じ操作をする必要もあり、gitでの管理もしにくいので方法Aが推奨です。
権限問題が発生する様々なケース
以降は権限関連で発生する代表的な5ケースをご紹介します。
ケース1:storageやbootstrap/cacheに書き込めない
エラー内容
The stream or file "/var/www/storage/logs/laravel.log" could not be opened
in append mode: Failed to open stream: Permission denied
や
file_put_contents(/var/www/bootstrap/cache/packages.php):
Failed to open stream: Permission denied
原因
Laravelは以下のディレクトリに書き込み権限が必要です。(閲覧する場合は閲覧権限も)
storage/app/storage/framework/cache/storage/framework/sessions/storage/framework/views/storage/logs/bootstrap/cache/
コンテナ内のプロセスのUID/GIDと、これらのディレクトリの所有者が一致しない場合に権限エラーが発生します。
ケース2: php artisan tinkerが動かない
エラー内容
ErrorException
Writing to directory /.config/psysh is not allowed.
原因
docker-compose.ymlでuser: "1000:1000"を指定しているが、コンテナ内にUID 1000のユーザーが存在しないケースです。
ユーザーが存在しないUIDでプロセスを実行すると、ホームディレクトリが解決できません。
tinkerが内部で使うpsyshは設定ファイルを~/.config/psyshに保存しようとしますが、~が不明なためルート直下の./config/psyshに下記行もとして権限エラーになります。
ケース3: composer installで権限がおかしくなる(頻発)
問題
composer install後にvendor/*ディレクトリがroot所有になり、アプリケーションやその後のcomposer`コマンドでエラーが発生する。
[ErrorException]
file_put_contents(/var/www/vendor/composer/installed.json): Failed to open stream: Permission denied
ケース4: chownがボリュームマウントで無効になる
問題
Dockerfileでchownを実行しても反映されない
WORKDIR /var/www
COPY . .
RUN chown -R appuser:appgroup /var/www
原因
docker-compose.ymlでボリュームマウントしている場合、コンテナ起動時にホスト側のディレクトリがコンテナ内のディレクトリを上書きしているため。
ケース5: artisanコマンドで生成したファイルの所有者がおかしい(頻発)
問題
php artisan make:controller等で生成されたファイルがroot所有になり、エディタで編集できない。
まとめ
- UID/GIDをホストと一致させる
- コンテナ内にユーザーを作成する
- rootでの操作をさける
権限問題の多くは「コンテナ内のUIDとホスト側のUIDが一致しない」ことが原因です。
UID/GIDの一致を最初に設定しておけば、大半のトラブルを未然に防ぐことができます。