參加你附近的 ,瞭解 VS Code 中的 AI 輔助開發。

將非 root 使用者新增到容器

許多 Docker 映象使用 root 作為預設使用者,但在某些情況下,你可能更喜歡使用非 root 使用者。如果你這樣做,你需要了解一些關於本地檔案系統(繫結)掛載的特殊情況。具體來說:

  • 適用於 Mac 的 Docker Desktop:在容器內部,任何掛載的檔案/資料夾都將表現為由你指定的容器使用者擁有。在本地,所有檔案系統操作都將使用你的本地使用者的許可權。

  • 適用於 Windows 的 Docker Desktop:在容器內部,任何掛載的檔案/資料夾都將顯示為由root擁有,但你指定的使用者仍然能夠讀/寫它們,並且所有檔案都將可執行。在本地,所有檔案系統操作都將使用你的本地使用者的許可權。這是因為從根本上無法將 Windows 風格的檔案許可權直接對映到 Linux。

  • Linux 上的 Docker CE/EE:在容器內部,任何掛載的檔案/資料夾都將擁有與容器外部完全相同的許可權——包括所有者使用者 ID (UID) 和組 ID (GID)。因此,你的容器使用者要麼需要擁有相同的 UID,要麼屬於具有相同 GID 的組。使用者/組的實際名稱無關緊要。機器上的第一個使用者通常會獲得 1000 的 UID,因此大多數容器都使用這個 ID 作為使用者的 ID,以嘗試避免此問題。

為 VS Code 指定使用者

如果你正在使用的映象或 Dockerfile 已經提供了一個可選的非 root 使用者(例如 node 映象),但仍然預設為 root,你可以透過在 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
    

建立非 root 使用者

雖然 Dev Containers 擴充套件附帶的任何映象或 Dockerfile 都將包含一個 UID/GID 為 1000 的非 root 使用者(通常稱為 vscodenode),但許多基礎映象和 Dockerfile 沒有。幸運的是,你可以更新或建立一個 Dockerfile,將非 root 使用者新增到你的容器中。

即使在生產環境中也建議以非 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: Rebuild Container 以應用更改。否則執行 Dev Containers: Open Folder in Container... 以連線到容器。

更改現有容器使用者的 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