Add a non-root user to a container
Many Docker images use root as the default user, but there are cases where you may prefer to use a non-root user instead. If you do so, there are somequirks with local filesystem (bind) mounts that you should know about. Specifically:
Docker Desktop for Mac: Inside the container, any mounted files/folders will act as if they are owned by the container user you specify. Locally, all filesystem operations will use the permissions of your local user instead.
Docker Desktop for Windows: Inside the container, any mounted files/folders will appear as if they are owned by
rootbut the user you specify will still be able to read/write them and all files will be executable. Locally, all filesystem operations will use the permissions of your local user instead. This is because there is fundamentally no way to directly map Windows-style file permissions to Linux.Docker CE/EE on Linux: Inside the container, any mounted files/folders will have the exact same permissions as outside the container - including the owner user ID (UID) and group ID (GID). Because of this, your container user will either need to have the same UID or be in a group with the same GID. The actual name of the user / group does not matter. The first user on a machine typically gets a UID of 1000, so most containers use this as the ID of the user to try to avoid this problem.
Specifying a user for VS Code
If the image or Dockerfile you are usingalready provides an optional non-root user (like thenode image) but still defaults to root, you can opt into having Visual Studio Code (server) and any sub-processes (terminals, tasks, debugging) use it by specifying theremoteUser property indevcontainer.json:
"remoteUser":"user-name-goes-here"On Linux, if you are referencing aDockerfile, image, or Docker Compose indevcontainer.json, this will also automatically update the container user's UID/GID to match your local user to avoid the bind mount permissions problem that exists in this environment (unless you set"updateRemoteUserUID": false).
Since this setting only affects VS Code and related sub-processes, VS Code needs to be restarted (or the window reloaded) for it to take effect. However, UID/GID updates are only applied when the container is created and requires a rebuild to change.
Specifying the default container user
In some cases, you may need all processes in the container to run as a different user (for example, due to startup requirements) rather than just VS Code. How you do this varies slightly depending on whether or not you are using Docker Compose.
Dockerfile and image: Add the
containerUserproperty to this same file."containerUser":"user-name-goes-here"On Linux, like
remoteUser, this will also automatically update the container user's UID/GID to match your local user to avoid the bind mount permissions problem that exists in this environment (unless you set"updateRemoteUserUID": false).Docker Compose: Update (orextend) your
docker-compose.ymlwith the following for the appropriate service:user:user-name-or-UID-goes-here
Creating a non-root user
While any images or Dockerfiles that come from the Dev Containers extension will include a non-root user with a UID/GID of 1000 (typically either calledvscode ornode), many base images and Dockerfiles do not. Fortunately, you can update or create a Dockerfile that adds a non-root user into your container.
Running your application as a non-root user is recommended even in production (since it is more secure), so this is a good idea even if you're reusing an existing Dockerfile. For example, this snippet for a Debian/Ubuntu container will create a user calleduser-name-goes-here, give it the ability to usesudo, and set it as the default:
ARG USERNAME=user-name-goes-hereARG USER_UID=1000ARG USER_GID=$USER_UID# Create the userRUN 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 $USERNAMETip: If you hit an error when building about the GID or UID already existing, the image you selected likely already has a non-root user you can take advantage of directly.
In either case, if you've already built the container and connected to it, runDev Containers: Rebuild Container from the Command Palette (F1) to pick up the change. Otherwise runDev Containers: Open Folder in Container... to connect to the container.
Change the UID/GID of an existing container user
While theremoteUser property tries to automatically update the UID/GID as appropriate on Linux when using aDockerfile or image, you can use this snippet in your Dockerfile to manually change the UID/GID of a user instead. Update theARG values as appropriate.
ARG USERNAME=user-name-goes-hereARG USER_UID=1000ARG USER_GID=$USER_UIDRUN groupmod --gid $USER_GID $USERNAME \ && usermod --uid $USER_UID --gid $USER_GID $USERNAME \ && chown -R $USER_UID:$USER_GID /home/$USERNAMENote that on Alpine Linux, you'll need to install theshadow package first.
RUN apk add --no-cache shadow