Visual Studio CodeのRemote Containers機能(Dev Containers)には、VSCodeの実行ユーザーのUIDでコンテナ内のユーザーのUIDを更新してくれる便利な機能があります。
例えば、UIDが1002のユーザーでVSCodeを立ち上げていて、コンテナ内で作成したユーザー devuser
を使用したとき、コンテナ内の devuser
のUIDは1002に上書きされるといった挙動になります。これは、手元のディレクトリをコンテナ内にマウントしていて、それをVSCodeでいじる場合に、UIDが異なってしまうという問題を回避することができるのでとても便利。
使い方
使い方は簡単で、devcontainer.json
に以下のように remoteUser
と updateRemoteUserUID
を指定するだけ。remoteUser
にコンテナイメージ内に存在するユーザー名を指定することでコンテナを開いたときに使用されるユーザーを指定でき、かつ updateRemoteUserUID
を有効にすると 指定したユーザーのUIDが現在のログインユーザーのUIDになってくれます。
{ "remoteUser": "devuser", "updateRemoteUserUID": true, }
説明のためupdateRemoteUserUID
も念のため指定していますが、このオプションはデフォルトで有効になっているので明示的な設定は省略可能です。
DevContainersに使用するコンテナイメージには、以下のようなDockerfileを考えてみます。
FROM ubuntu:20.04 ARG USERNAME=devuser ARG USER_UID=1234 ARG USER_GID=$USER_UID # Create the user RUN groupadd --gid $USER_GID $USERNAME \ && useradd --uid $USER_UID --gid $USER_GID -m -s /bin/bash $USERNAME
Dockerfile では UID 1234 で devuser
というユーザーが作成されていますが、Dev Containersで開いてみると、見事IDなどが変わっていることがわかります。
devuser@cbb03f77d869:/workspaces/devcontainer_example$ id uid=1000(devuser) gid=1000(devuser) groups=1000(devuser) devuser@cbb03f77d869:/workspaces/devcontainer_example$ ls /home/devuser -la total 28 drwxr-xr-x 1 devuser devuser 4096 Jan 12 04:17 . drwxr-xr-x 1 root root 4096 Jan 12 04:17 .. -rw-r--r-- 1 devuser devuser 220 Feb 25 2020 .bash_logout -rw-r--r-- 1 devuser devuser 3771 Feb 25 2020 .bashrc -rw-r--r-- 1 devuser devuser 807 Feb 25 2020 .profile drwxr-xr-x 6 devuser devuser 4096 Jan 12 04:17 .vscode-server
ちゃんと HOME のパーミッションも変わっていてとてもGOODですね。
問題点
「指定したユーザーのUIDが現在のログインユーザーのUIDになってくれます」と書きましたが、これが効かないケースもありました。
というのも、変更先のUID(つまりログインユーザーのUID)がコンテナイメージ内ですでに使われていた場合、このオプションは有効に働かず、コンテナイメージ内のUIDがそのまま使われてしまいます。
例えば、「node」のコンテナイメージはデフォルトで node
というユーザーがUIDが1000で作成されているので、VSCodeを起動しているユーザーのUIDが1000だった時にバッティングしてしまい、devuser
は作成した時点の UID 1234 の状態のままでDev Containersが立ち上がってしまいました。
解決方法
ここで、この問題を解決できる方法を考えてみました。
1. そのユーザーをそのまま開発にも使う
すでに使いたいUIDが使用されてしまっているのであれば、remoteUser
にそのUIDが割り当てられているユーザーを指定してしまうのも手です。
ただ、これだとユーザー名が自由に選べませんし、意図した通りにセットアップされているかはDockerfileを読み解いていくしかありません。そもそも、Dev Contaienrsで乗り込むコンテナにユーザーがあったとしても、そのユーザーをそのまま活用するケースに出会ったことがありませんし、こういうユーザーは封印前提で次に示す解決策2を取るのがいいのかなと思います。
2. そのユーザーのUIDを変えてしまう
1でも書きましたが、これはこのユーザーがDockerfile作者の想定した通りに使えなくなる可能性があるので、「封印前提」で考えるべきでしょう。
RUN groupmod -g 12345 node && \ usermod -u 12345 -g 12345 node
上記のように、node
ユーザーがすでに使いたいUIDを使っていて邪魔なのであれば、そのユーザーのUIDを使わない値にしてしまえという発想です。(消しちゃってもいいのかもしれない)
このようにすることで、uid 1000がすでに使われていたとしてもログインユーザーのUIDに合わせてDevContainers内のUIDを上書きすることができるようになりました。
終わりに
以上、ゴリゴリっと書いてしまいましたが、DevContainersのremoteUser
の問題と対処でした。
(読み返すとUID, VSCode, DevContainersと表現が揺れまくっているのが気になる…)