コンテナーに非ルートユーザーを追加する
多くの Docker イメージではルートがデフォルトのユーザーとして使用されますが、代わりに非ルートユーザーを使用したい場合もあります。そのようにする場合、ローカルファイルシステム (バインド) マウントにはいくつかの癖があることを知っておく必要があります。具体的には、
-
Docker Desktop for Mac: コンテナー内では、マウントされたファイル/フォルダーは、指定したコンテナーユーザーが所有しているかのように動作します。ローカルでは、すべてのファイルシステム操作はローカルユーザーの権限を使用します。
-
Docker Desktop for Windows: コンテナー内では、マウントされたファイル/フォルダーは
root
が所有しているかのように見えますが、指定したユーザーはそれらを読み書きでき、すべてのファイルは実行可能です。ローカルでは、すべてのファイルシステム操作はローカルユーザーの権限を使用します。これは、Windows スタイルのファイル権限を Linux に直接マッピングする方法が根本的にないためです。 -
Linux 上の Docker CE/EE: コンテナー内では、マウントされたファイル/フォルダーは、コンテナー外とまったく同じ権限を持ちます。これには、所有者ユーザー ID (UID) とグループ ID (GID) も含まれます。このため、コンテナーユーザーは、同じ UID を持つか、同じ GID を持つグループに属する必要があります。ユーザー/グループの実際の名前は関係ありません。通常、マシンの最初のユーザーは UID 1000 を取得するため、ほとんどのコンテナーではこの問題を回避するためにこれをユーザーの ID として使用します。
VS Code のユーザーを指定する
使用しているイメージまたは Dockerfile が既にオプションの非ルートユーザーを提供している (node
イメージのように) が、デフォルトではルートである場合、devcontainer.json
で remoteUser
プロパティを指定することで、Visual Studio Code (サーバー) とすべてのサブプロセス (ターミナル、タスク、デバッグ) がそれを使用するように選択できます。
"remoteUser": "user-name-goes-here"
Linux では、devcontainer.json
で Dockerfile、イメージ、または Docker Compose を参照している場合、この環境に存在するバインドマウントの権限の問題を回避するために、コンテナーユーザーの UID/GID をローカルユーザーと一致するように自動的に更新します ("updateRemoteUserUID": false
を設定しない限り)。
この設定は VS Code と関連するサブプロセスにのみ影響するため、変更を有効にするには VS Code を再起動 (またはウィンドウを再読み込み) する必要があります。ただし、UID/GID の更新はコンテナーが作成されたときにのみ適用され、変更には再構築が必要です。
デフォルトのコンテナーユーザーを指定する
場合によっては、VS Code だけでなく、コンテナー内のすべてのプロセスを別のユーザーとして実行する必要がある場合があります (たとえば、起動要件のため)。これを行う方法は、Docker Compose を使用しているかどうかによってわずかに異なります。
-
Dockerfile とイメージ: この同じファイルに
containerUser
プロパティを追加します。"containerUser": "user-name-goes-here"
Linux では、
remoteUser
と同様に、この環境に存在するバインドマウントの権限の問題を回避するために、コンテナーユーザーの UID/GID をローカルユーザーと一致するように自動的に更新します ("updateRemoteUserUID": false
を設定しない限り)。 -
Docker Compose: 適切なサービスの
docker-compose.yml
を次の内容で更新 (または拡張) します。user: user-name-or-UID-goes-here
非ルートユーザーを作成する
Dev Containers 拡張機能から提供されるイメージまたは Dockerfile には、UID/GID 1000 の非ルートユーザー (通常は vscode
または node
と呼ばれます) が含まれていますが、多くのベースイメージや Dockerfile には含まれていません。幸いなことに、非ルートユーザーをコンテナーに追加する Dockerfile を更新または作成できます。
非ルートユーザーとしてアプリケーションを実行することは、本番環境でも推奨されます (より安全であるため)。したがって、既存の Dockerfile を再利用している場合でもこれは良い考えです。たとえば、Debian/Ubuntu コンテナーのこのスニペットは、user-name-goes-here
というユーザーを作成し、sudo
を使用する機能を付与し、それをデフォルトとして設定します。
ARG USERNAME=user-name-goes-here
ARG USER_UID=1000
ARG USER_GID=$USER_UID
# Create the user
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
#
# [Optional] Add sudo support. Omit if you don't need to install software after connecting.
&& apt-get update \
&& apt-get install -y sudo \
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME
# ********************************************************
# * Anything else you want to do like clean up goes here *
# ********************************************************
# [Optional] Set the default user. Omit if you want to keep the default as root.
USER $USERNAME
ヒント: ビルド時に GID または UID が既に存在するというエラーが発生した場合、選択したイメージには既に直接利用できる非ルートユーザーが存在する可能性があります。
どちらの場合でも、コンテナーを既にビルドして接続している場合は、コマンドパレット (F1) から開発コンテナー: コンテナーを再構築を実行して変更を反映させます。そうでない場合は、開発コンテナー: コンテナーでフォルダーを開く...を実行してコンテナーに接続します。
既存のコンテナーユーザーの UID/GID を変更する
remoteUser
プロパティは、Dockerfile またはイメージを使用している場合に Linux で UID/GID を適切に自動更新しようとしますが、この Dockerfile スニペットを使用して、ユーザーの UID/GID を手動で変更できます。ARG
の値を適切に更新してください。
ARG USERNAME=user-name-goes-here
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN groupmod --gid $USER_GID $USERNAME \
&& usermod --uid $USER_UID --gid $USER_GID $USERNAME \
&& chown -R $USER_UID:$USER_GID /home/$USERNAME
Alpine Linux では、最初に shadow
パッケージをインストールする必要があることに注意してください。
RUN apk add --no-cache shadow