컨테이너에 루트가 아닌 사용자 추가
많은 Docker 이미지에서 기본 사용자로 root를 사용하지만, 루트가 아닌 사용자를 대신 사용하는 것이 더 나은 경우가 있습니다. 그렇게 할 경우, 로컬 파일 시스템(바인드) 마운트에 대한 몇 가지 특이점이 있다는 것을 알아두셔야 합니다. 구체적으로는 다음과 같습니다.
-
Mac용 Docker Desktop: 컨테이너 내부에서는 마운트된 파일/폴더가 지정한 컨테이너 사용자가 소유한 것처럼 작동합니다. 로컬에서는 모든 파일 시스템 작업이 대신 로컬 사용자의 권한을 사용합니다.
-
Windows용 Docker Desktop: 컨테이너 내부에서는 마운트된 파일/폴더가
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)에서 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