WSL2でdocker-compose runコマンドで生成されたファイルの更新ができない

yosiです。

WSL2上でdocker-compose run app bundle exec rails new .コマンドによってファイルを生成したとき、ファイルの編集ができなかったり、git add したときに .git/index.lock ファイルで Permission denied が出たりしていました。

$ git add .
fatal: Unable to create '/home/username/dev/rails-project/.git/index.lock': Permission denied

WSL 特有の症状なのかと悩んでいたのですが、docker-compose run app bundle exec rails new .コマンドのようにコンテナ内からコマンドを実行してファイルを生成すると所有者がrootになることが原因のようでした。

生成されたファイルやフォルダの所有者がrootなので、所有者以外である現在のユーザーアカウントでは書き込みができなかったのです。

原因

docker-compose run app bundle exec rails new .

のようにコンテナ内でコマンドを実行しファイルやフォルダを生成すると、ファイルやフォルダの所有者やグループがrootとなってしまいます。

実際に見ていきましょう。rails-projectというフォルダ内でrails newします。

rails-project$ docker-compose run app bundle exec rails new . --database postgresql --skip-action-text --skip-active-storage --skip-action-cable --skip-turbolinks --skip-javascript --skip-system-test --skip-webpack-install --skip-sprockets --skip-test

生成されたファイルをlsコマンドで確認すると、生成されたファイルがrootになってるのが確認できます。

rails-project$ ls -l
total 68
-rw-r--r-- 1 username username  162 Sep 28 20:32 Dockerfile
-rw-r--r-- 1 username username 1534 Sep 29 01:14 Gemfile
-rw-r--r-- 1 username username 4315 Sep 29 01:14 Gemfile.lock
-rw-r--r-- 1 root     root      374 Sep 29 01:14 README.md
-rw-r--r-- 1 root     root      227 Sep 29 01:14 Rakefile
drwxr-xr-x 9 root     root     4096 Sep 29 01:14 app
drwxr-xr-x 2 root     root     4096 Sep 29 01:14 bin
drwxr-xr-x 5 root     root     4096 Sep 29 01:14 config
-rw-r--r-- 1 root     root      160 Sep 29 01:14 config.ru
drwxr-xr-x 2 root     root     4096 Sep 29 01:14 db
-rw-r--r-- 1 username username  694 Sep 28 20:32 docker-compose.yml
drwxr-xr-x 4 root     root     4096 Sep 29 01:14 lib
drwxr-xr-x 2 root     root     4096 Sep 29 01:14 log
drwxr-xr-x 2 root     root     4096 Sep 29 01:14 public
drwxr-xr-x 4 root     root     4096 Sep 29 01:14 tmp
drwxr-xr-x 2 root     root     4096 Sep 29 01:14 vendor

例えばREADME.mdの権限は-rw-r--r--となっています。

これは

 所有者のパーミッション  グループのパーミッション  その他のユーザーのパーミッション
-  rw-  r—  r—

のように3つずつ分割できます。

rは書き込み可能、wは書き込み可能、xは実行可能、-は不可を表しています。

つまり、Dockerfileなどは所有者のパーミッションがrw-で、所有者アカウント(上でいうusername)からアクセスするときは書き込みと読み込みができます。

逆にREADME.mdは所有者がrootなので、rootアカウントからアクセスすると書き込みと読み込みができる一方、それ以外のアカウント(例えばusernameアカウント)だと読み込み権限しかありません。

これがファイルの編集などができない原因です。

解決策

いろいろと解決策はありそうでしたが根本的によさそうなものはあまり見つかりませんでした。

例えばコンテナ内とホスト側でUIDなどをそろえる方法、デフォルトユーザーアカウントをroot権限にしてしますことなどがありそうです。

https://teratail.com/questions/316472

https://futureys.tokyo/how-permission-should-be-set-for-developing-inside-a-container-using-wsl-2/

しかし、前者は面倒そうですし、後者もやってもよさそうですができればやりたくありません(rootでログインすると権限周りで悩むことはなくなりそうなのは魅力ですが)。

また、その他のユーザーのパーミッションを変更するという手もありますが、それをやるならファイルの所有者を変更するべきでしょう。

そこで僕はプロジェクトフォルダ内の全てのファイル、フォルダの所有者、グループを変更することにしました。

chownコマンドで変更します。

$ chown [オプション] ユーザー[:グループ] ファイル

-Rオプションをつけることで指定したフォルダ内を再帰的に変更してくれます。

Railsの1つ上のディレクトリに移動して、Railsプロジェクトフォルダ内のすべてのファイル、フォルダに適用させます。

ついでにグループも変更しておきます。

dev/rails-project$ cd ../
dev$ sudo chown -R username:username rails-project
dev$ cd rails-project

lsコマンドで確認すると所有者が変更されているのを確認できると思います。

dev/rails-project$ ls -l
total 68
-rw-r--r-- 1 username username  162 Sep 28 20:32 Dockerfile
-rw-r--r-- 1 username username 1534 Sep 29 01:14 Gemfile
-rw-r--r-- 1 username username 4315 Sep 29 01:14 Gemfile.lock
-rw-r--r-- 1 username username  374 Sep 29 01:14 README.md
-rw-r--r-- 1 username username  227 Sep 29 01:14 Rakefile
drwxr-xr-x 9 username username 4096 Sep 29 01:14 app
drwxr-xr-x 2 username username 4096 Sep 29 01:14 bin
drwxr-xr-x 5 username username 4096 Sep 29 01:14 config
-rw-r--r-- 1 username username  160 Sep 29 01:14 config.ru
drwxr-xr-x 2 username username 4096 Sep 29 01:14 db
-rw-r--r-- 1 username username  694 Sep 28 20:32 docker-compose.yml
drwxr-xr-x 4 username username 4096 Sep 29 01:14 lib
drwxr-xr-x 2 username username 4096 Sep 29 01:14 log
drwxr-xr-x 2 username username 4096 Sep 29 01:14 public
drwxr-xr-x 4 username username 4096 Sep 29 01:14 tmp
drwxr-xr-x 2 username username 4096 Sep 29 01:14 vendor

これで問題なく編集などの操作ができるようになりました。

根本的に解決してはいませんが、コンテナの中からコマンドでファイル作成をしなければ起きることがないので、頻度は低そうです。

今後は今回と同じようにコンテナ内からコマンドを打った後に権限を変更するか、wsl内に直接Rubyをインストールしてrailsコマンドはコンテナから実行しないようにするのがいいと思います。

本件に関係なくてやっても意味がなかった対応

おまけです。

wsl.confや .wslconfigを編集して一般ユーザアカウントをデフォルトのユーザにすれば解決するかもと思ったのですが、全く関係なかったです。
というかもとからデフォルトに設定されてる気が。

$ cat << EOF > /etc/wsl.conf
[user]
default=username
EOF

ubuntu2004 config --default-user robertを実行するというのも同じく意味がありませんでした。
複数サイトにubuntu20.04コマンドと書いてありましたが、そのコマンドは実行できなくてubuntu2004コマンドなら動きました。

まとめ

手こずってしまい、自身のパーミッション関係の知識不足を痛感しました。

しかし、いろいろと勉強する機会になってよかったです。

パーミッションはこのあたりの記事がわかりやすかったです。

https://kazmax.zpp.jp/linux_beginner/default_permission.html http://www.rivhiro-weather.com/knowledge/?p=168

今回はWSL固有の問題ではなかったですが、「WSLの問題化も」って可能性があるだけで考えることが増えてしまうのでしんどいなと思いました。