Docker for WindowsとWSLを併用するときのパーミッションとファイルユーザ
Web開発をWindowsからやってもいいよね、特にフロントエンド。
みんなが使ってるWindowsのブラウザでの動作って気になるじゃん。
というわけで、Docker for WindowsとWSLの併用を始めることにしました。
Git for Windowsはちょっと大変そう、一方でWSLはDockerで動かしたWebコンテンツをWindowsのブラウザで見るのが大変そう。
なので、WSLでGitを使い、Docker for Windowsで開発に必要なプロセスを起動する、という変態チックなことをすることにしました。
ちなみにエディタはWindows版VSCodeです。
何が問題になるのか?
パーミッション管理がまともに出来ないという問題があります。ファイルオーナーとグループの設定が変に見えやすいです。
特にDockerコンテナの中で作ったファイルをWSLから見ると、なんだこれ?って感じになります。
そして、WSLから編集ができないのです。
実例を挙げると、以下のような感じです。
これは空のディレクトリにDockerfileとdocker-composeを作り、そこでDockerコンテナに入ってから npm install zenn-cli
を実行しただけの状態です。
rotelstift@in_docker_container:~$ ls -la
total 320
drwxrwxrwx 1 root root 512 Oct 3 16:18 .
drwxr-xr-x 1 root root 4096 Oct 3 14:04 ..
drwx------ 1 rotelstift rotelstift 512 Oct 3 16:16 .config
drwxr-xr-x 1 rotelstift rotelstift 512 Oct 3 16:18 .npm
-rwxrwxrwx 1 root root 260 Oct 3 16:10 Dockerfile
-rwxrwxrwx 1 root root 159 Oct 3 16:15 docker-compose.yml
drwxr-xr-x 1 rotelstift rotelstift 512 Oct 3 16:18 node_modules
-rw-r--r-- 1 rotelstift rotelstift 320621 Oct 3 16:18 package-lock.json
このディレクトリをWSLの側から見てみます。
rotelstift@in_WSL:FullPathTo/test$ ls -la
total 316
drwxrwxrwx 1 rotelstift rotelstift 512 Oct 4 01:18 .
drwxrwxrwx 1 rotelstift rotelstift 512 Oct 4 00:57 ..
drwx------ 1 1001 docker 512 Oct 4 01:16 .config
drwxr-xr-x 1 1001 docker 512 Oct 4 01:18 .npm
-rwxrwxrwx 1 rotelstift rotelstift 260 Oct 4 01:10 Dockerfile
-rwxrwxrwx 1 rotelstift rotelstift 159 Oct 4 01:15 docker-compose.yml
drwxr-xr-x 1 1001 docker 512 Oct 4 01:18 node_modules
-rw-r--r-- 1 1001 docker 320621 Oct 4 01:18 package-lock.json
一見すると、何がどうなっているのかわかりません。
これを読み解いていきます。
前提条件
まず、WSL2ではUbuntuをインストールし、普段はrotelstiftというユーザで利用しています。
また、Dockerfileとdocker-compose.ymlは以下のようにして、やはりrotelstiftというユーザで使うようにしています。
FROM node:latest
RUN apt-get update
RUN apt-get install sudo
ENV USER rotelstift
ENV HOME /home/${USER}
RUN useradd -m ${USER}
RUN gpasswd -a ${USER} sudo
RUN echo "${USER}:passwd" | chpasswd
USER ${USER}
WORKDIR ${HOME}
CMD ["/bin/bash"]
version: '3'
services:
test:
build: .
image: test
ports:
- "8080:8000"
volumes:
- C:\Users\rotel\src\test:/home/rotelstift
問題整理
WSLの側から見て、不明なユーザ1001によって作られたファイルが編集できないのが一番の問題です。
何故かVSCodeからも編集出来ないことがあります。
ちなみにDocker for Macではこのような問題は起きません。
では、これから分かったことをまとめていきます。
WSLでユーザ1001、グループDockerになるファイル
この所有権がついてしまうファイルは、Dockerの中ではユーザrotelstift、グループrotelstiftになっているファイルです。
つまり、Dockerコンテナの中で作られたファイルになります。
WSLでユーザrotelstift、グループrotelstiftになるファイル
この所有権が(ついでにパーミッション777が)ついてしまうファイルは、Dockerの中ではユーザroot、グループrootになっているファイルです。
このファイルはDockerコンテナの外、WindowsかWSLで作られたファイルになります。
一方通行の所有権管理
ここでDocker内とWSLの側で id
コマンドを使ってユーザID、グループIDを調べてみましょう。
rotelstift@in_docker_container:~$ id
uid=1001(rotelstift) gid=1001(rotelstift) groups=1001(rotelstift),27(sudo)
rotelstift@in_WSL:FullPathTo/test$ id
uid=1000(rotelstift) gid=1000(rotelstift) groups=1000(rotelstift),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),117(netdev),1001(docker)
当たり前の話ですが、DockerコンテナとWSLの側でrotelstiftのユーザIDが違っています。
Dockerコンテナ内でのrotelstiftは uid=1001(rotelstift) gid=1001(rotelstift)
です。
ただ、ここで着目したいのはDockerコンテナ内では gid=1001(rotelstift)
に対し、WSLでは groups=1001(docker)
になっていることです。
そして、Dockerコンテナ内で作られたファイルはユーザ1001、グループdockerだったことを思い出すと、Dockerコンテナ内で作られたファイルの所有権IDはWSL内でも引き継がれるのではないかという仮説が立てられます。
試しにWSLで次のコマンドを打ってみると、 cat /etc/passwd | grep uid=1001
結果は出てきません。
つまり、Dockerコンテナ内で作られたファイルの所有権はコンテナの外でも同じなのです。ただ、コンテナの外、WSLの側にその所有権IDに対応するユーザやグループがあったりなかったりする、という話なのです。
一方でその逆はないように見えます。
WSLの側でuid=1000 gid=1000で作られたファイルは、すべてrootとしてマウントされます。ちなみにrootはDockerコンテナ内でもWSLでも uid=0(root) gid=0(root) groups=0(root)
です。
ここで試しにDockerコンテナ内で sudo touch page
とやってみましょう。
コンテナ内では
rotelstift@in_docker_container:~$ ls -la page
-rw-r--r-- 1 root root 0 Oct 4 03:33 page
となります。これをWSLから見たときに、ユーザrotelstift、グループrotelstiftになっているでしょうか?
rotelstift@in_WSL:FullPathTo/test$ ls -la page
-rw-r--r-- 1 root root 0 Oct 4 12:33 page
なっていません。
やはり、Dockerコンテナ内で作られたファイルの所有権IDはWSL内でも引き継がれるけれども、その逆はないことがわかります。
一応、その逆も試してみましょう。WSL内で touch hoge
して、それをDockerコンテナの中からみたらどうなるでしょうか?
rotelstift@in_WSL:FullPathTo/test$ touch hoge
rotelstift@in_WSL:FullPathTo/test$ ls -la hoge
-rwxrwxrwx 1 rotelstift rotelstift 12 Oct 4 12:02 hoge
rotelstift@3eb35cef6f47:~$ ls -la hoge
-rwxrwxrwx 1 root root 12 Oct 4 03:02 hoge
やはりWSL内で作られたファイルはrootの所有(ただし777)でマウントされます。
Dockerコンテナ内で作られたファイルをどうすれば編集できるようになるのか
これに関しては答えが明白です。
Dockerコンテナ内で作られた全てのファイルはWindowsで編集するべきです。
いちいちパーミッションを直すのは面倒すぎます。そして、WSLはパーミッションを守りますが、Windowsは無視します。
とは言え、Windows版のVSCodeでも編集ができないことがありました。けれどもそのからくりは簡単で、VSCodeからremote-WSLに接続して文書を編集する機能があるのですが、それを使っているとWSLの制約を受けるのです。
なので、その機能を使わないで本当にWindowsの側だけでファイルを編集するといろいろと悩まなくて済みます。
感想
最初はWindows側ならパーミッションを無視することに気づかず、どうにかしてDockerコンテナ内で作られたファイルの所有権IDとWSL内の所有権IDを一致させられないかと頑張ってみましたが、最終的にはWSL側のrotelstiftのuidを変更しなければならないというところに来てしまって、そんな怖いこと出来んわ、ということで諦めました。
諦めたところでWindows側はパーミッションをさくっと無視することに気が付いて、井上陽水の夢の中への歌詞を思い出したりしました。
remote-WSLに接続していないとVSCode内でGitが使えなかったりしますが、ちゃんとコマンドラインからGitを使えばいいだけの話なのでそのデメリットは甘受する、といった感じです。
Discussion
初めまして、現在プログラム勉強中の者です。
当方も当記事と同じ問題にぶつかり、解決策として
コンテナ内のユーザーidをwsl側のidと一致させることでwsl-remoteに接続したVScode上でファイル編集することが出来ています。
この方法は何か問題が考えられますでしょうか?ご教授頂きたくコメントさせて頂きます。
コンテナの側のuidをWSLに合わせていらっしゃるなら問題はないと思います。
この記事を書くにあたって調べた範囲ではコンテナのuidを調整する方法が見当たらず、WSL側のuidを変更するしかなさそうに見えたので、それはたぶん最悪WSLが使えなくなる可能性があると思って諦めたのでした。
ご回答頂きありがとうございます!
WSLをrootで操作するのは怖いですよね。。。