コンテナーに非 root ユーザーを追加する

多くの Docker イメージはデフォルトユーザーとして root を使用していますが、代わりに非 root ユーザーを使用したい場合があります。その場合、ローカルファイルシステム(バインド)マウントに関するいくつかの注意点があります。具体的には

  • 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 がすでにオプションの非 root ユーザーを提供しているnode イメージなど)が、依然としてデフォルトで root になっている場合、devcontainer.jsonremoteUser プロパティを指定することにより、Visual Studio Code(サーバー)およびすべてのサブプロセス(ターミナル、タスク、デバッグ)でそれを使用するように選択できます。

"remoteUser": "user-name-goes-here"

Linux では、devcontainer.jsonDockerfile、イメージ、または 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
    

非 root ユーザーを作成する

Dev Containers 拡張機能から提供されるイメージまたは Dockerfile には、UID/GID が 1000 の非 root ユーザー(通常は vscode または node と呼ばれます)が含まれていますが、多くのベースイメージおよび Dockerfile には含まれていません。幸いなことに、コンテナーに非 root ユーザーを追加する Dockerfile を更新または作成できます。

アプリケーションを非 root ユーザーとして実行することは、本番環境でも推奨されています(より安全であるため)。したがって、既存の 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 がすでに存在するというビルド時のエラーが発生した場合、選択したイメージには、直接利用できる非 root ユーザーがすでに存在している可能性があります。

どちらの場合も、すでにコンテナーをビルドして接続している場合は、コマンドパレット (F1) から Dev Containers: コンテナーのリビルド を実行して、変更を反映させます。それ以外の場合は、Dev Containers: コンテナーでフォルダーを開く... を実行してコンテナーに接続します。

既存のコンテナーユーザーの 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