ホスト側のファイル・フォルダをバインドする時、windowsだと強制的にrootになるのがツラすぎる。
バリバリ開発してる人、どうやってるか教えて下さいませ
再現用のファイル一式は以下の通り。windows10で、WSLではなくwindows側のフォルダに設置する。
//.env
COMPOSE_PROJECT_NAME=docker-file-volume-test
//docker-compose.yml
services:
node-sys-container:
build:
context: .
dockerfile: ./Dockerfile
volumes:
- type: bind
source: ./
target: /app/bind
//Dockerfile
FROM node:18.4.0-alpine3.15
USER node
WORKDIR /app
RUN touch /app/touch-file
CMD ["node","/app/bind/index.js"]
//index.js
(async()=>{
let counter = 1;
while(true){
console.log(`loop ${counter++}`);
await new Promise(resolve => { setTimeout(() => { resolve() }, 1 * 1000) });
}
})();
//package.json
{
"main": "index.js",
"scripts": {
"start": "node index.js"
}
}
上記ファイルを設置したフォルダで以下のコマンドを実行
docker compose down && docker compose up -d --build && docker compose exec node-sys-container sh
以下の様に、Dockerfileの中で作られたフォルダやファイルはnodeユーザーになっているが、docker-compose側でbindしたフォルダはroot権限になっている
/app $ ls -lav
total 8
drwxr-xr-x 1 node node 4096 Jul 2 15:28 .
drwxr-xr-x 1 root root 4096 Jul 2 15:28 ..
drwxrwxrwx 1 root root 4096 Jul 2 15:06 bind
-rw-r--r-- 1 node node 0 Jul 2 15:23 touch-file
node.jsの場合、nodeのプロセスは非rootユーザー(node という名前のユーザー) で実行するべきとされている。
https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#non-root-user
bindしたファイル・フォルダはrootユーザー、nodeプロセスは非rootユーザーなのでどうにもならない。
解決策としては
- nodeプロセスをrootユーザーで動かす。nodeを非rootで動かすのは「最小特権の原則」の為とされているからなのでrootで動かすのもアリのはず。
- nodeプロセスをrootで動かした時のトラブル解決が面倒になる?「ずっとrootでやってるけど別に困らない」という情報があれば安心出来るが…
- ファイル一式をwindows側ではなくWSL内のパスに設置する。これならlinux/macでUID GIDを一致させる数々のテクニックが使える。
-. 現実的にはこれが最適解なんだろうが、UID GIDの沼に浸かる必要があるのか… - docker composeではなく、Dockerfile側でaddやcopyする
-. 短絡的にはこれ。本番リリース時ならいいけど、開発時にファイルを1行弄るたびに再ビルドするのは…
bind時に任意のユーザー権限でと指定出来るようになれば万事解決なんだがなぁ
どうすればいいんだ