`/workspaces` is created by `root`, but I am a "non-root" user (rootless docker & non-root user)

Hello. I have just started learning Linux and Docker. My goal is to set up a non-root development environment with rootless Docker on a remote Ubuntu machine. I tried to get it done myself, but it’s been a nightmare for almost a week. I followed these guides:

Basic Information

Local machine

  • User name: heston-pablo
  • Host name: laptop
  • OS: Windows 11 Home 23H2
  • Editor: VS Code 1.93.1
  • Terminal: Git bash
heston-pablo@laptop MINGW64 ~
$ cat ~/.ssh/config
Host desktop
        Hostname 192.168.35.79
        User heston-pablo
        Port 49761
        AddKeysToAgent yes
        IdentityFile ~/.ssh/id_ed25519
        ForwardAgent yes

Remote machine

  • User name: heston-pablo
  • Host name: desktop
  • OS: Ubuntu 24.04.1
  • Docker: Docker Engine 27.2.1
heston-pablo@desktop:~$ id -u
1000

heston-pablo@desktop:~$ whoami
heston-pablo

heston-pablo@desktop:~$ grep ^$(whoami): /etc/subuid
heston-pablo:100000:65536

heston-pablo@desktop:~$ grep ^$(whoami): /etc/subgid
heston-pablo:100000:65536

heston-pablo@desktop:~$ systemctl status docker
○ docker.service - Docker Application Container Engine
     Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; preset: enabled)
     Active: inactive (dead)
TriggeredBy: ○ docker.socket
       Docs: https://docs.docker.com

heston-pablo@desktop:~$ systemctl --user status docker
● docker.service - Docker Application Container Engine (Rootless)
     Loaded: loaded (/home/heston-pablo/.config/systemd/user/docker.service; enabled; preset: enabled)
     Active: active (running) since Tue 2024-09-17 17:42:53 KST; 1h 57min ago
       Docs: https://docs.docker.com/go/rootless/
   Main PID: 1369 (rootlesskit)
      Tasks: 53
     Memory: 139.6M (peak: 142.5M)
        CPU: 5.071s
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/docker.service
             ├─1369 rootlesskit --state-dir=/run/user/1000/dockerd-rootless --net=slirp4netns --mtu=65520 --slirp4netns>
             ├─1405 /proc/self/exe --state-dir=/run/user/1000/dockerd-rootless --net=slirp4netns --mtu=65520 --slirp4ne>
             ├─1438 slirp4netns --mtu 65520 -r 3 --disable-host-loopback --enable-sandbox --enable-seccomp 1405 tap0
             ├─1464 dockerd
             └─1605 containerd --config /run/user/1000/docker/containerd/containerd.toml

What I did

  1. Open git bash on local
  2. Open VS Code with code command
  3. Connect to host using the Remote - SSH extension
  4. Open ~/repos directory
  5. Create test-container directory
  6. Create .devcontainer/devcontainer.json
// devcontainer.json
{
	"name": "Node.js & TypeScript",
	"image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm"
}
  1. Dev Containers: Open Folders in Container

Problem

While the /workspaces directory is created by root, I am a non-root user node. So I cannot create or edit inside the initial /workspaces/test-container directory.

node ➜ /workspaces/test-container $ id
uid=1000(node) gid=1000(node) groups=1000(node),998(nvm),999(npm)

node ➜ /workspaces/test-container $ ls -al
total 12
drwxrwxr-x 3 root root 4096 Sep 17 11:00 .
drwxr-xr-x 3 root root 4096 Sep 17 11:03 ..
drwxrwxr-x 2 root root 4096 Sep 17 11:00 .devcontainer

node ➜ /workspaces/test-container $ cd ~

node ➜ ~ $ ls -al
total 68
drwxr-xr-x  1 node node 4096 Sep 17 11:03 .
drwxr-xr-x  1 root root 4096 Sep  5 00:15 ..
-rw-r--r--  1 node node  220 Mar 29 19:40 .bash_logout
-rw-r--r--  1 node node 5640 Sep 12 18:01 .bashrc
drwxr-xr-x  3 node node 4096 Sep 17 11:03 .cache
drwxr-xr-x  1 node node 4096 Sep 17 11:03 .config
drwxr-xr-x  3 node node 4096 Sep 17 11:03 .dotnet
-rw-r--r--  1 node node  263 Sep 17 11:03 .gitconfig
drwx------  2 node node 4096 Sep 17 11:03 .gnupg
drwxrwxr-x  1 node node 4096 Sep 12 18:01 .npm
drwxr-xr-x 12 node node 4096 Sep 12 18:01 .oh-my-zsh
-rw-r--r--  1 node node  807 Mar 29 19:40 .profile
drwxr-xr-x  2 node node 4096 Sep 17 11:03 .ssh
drwxr-xr-x  6 node node 4096 Sep 17 11:03 .vscode-server
-rw-r--r--  1 node node   22 Sep 12 18:01 .zprofile
-rw-r--r--  1 node node 4033 Sep 12 18:01 .zshrc

After reading tons of articles, docs, and other resources, I’ve come to roughly understand namespaces, UID/GID, remapping, etc. But I don’t understand the reasoning behind certain aspects.

Does Docker assume that I would want to be a root user inside a devcontainer when I start a new one? Why does it create /workspaces with the root user and place me inside /workspaces/test-container by default, rather than the user’s ~/ directory where I can do what I want? Is “non-root user on rootless Docker” a minor approach?

And why can’t I use docker inside a devcontainer? Should I expose a host’s Docker socket to the devcontainer or just go for Docker-in-Docker?

Please let me know if you need more information.

It is only root in the container, not on the host. That is what rootless containers do. The root user in the container is actually your user on the host. Same userid just different username, except the user id seems to be different when checking it in the container. That is what a user namespace does. Which is used by a rootless container.

Why the container does not open in a folder of a non-root user even in the container, that could only be answered by the image maintainer, but since it will not be root on the host, it doesn’t matter much.in a dev container and you wouldn’t be able to install anything in the container if you were not a root in the container unless you rebuild the image.

1 Like

I apologize for the delayed response. Your previous answers regarding namespaces have been immensely helpful in understanding the concept. After extensive study, I’ve concluded that the issue isn’t with rootless Docker itself, but rather with the devcontainer functionality, as you mentioned.

If I may ask, do you use rootless Docker together with devcontainers, rimelek? I’m not entirely certain whether I’m doing something incorrectly or if the devcontainer feature itself is the problem. I’m curious to know how an experienced user like yourself approaches this. Would you mind sharing your experience or insights on this matter?

I’m not using Devcontainers. I work on macOS and Linux so the permissions are compatible with Linux containers and I have no other reason currently to use devcontainers. Especially not on a remote server where I only run production version of the applications.

I tried the Dev Environment feature of Docker Desktop just to learn about it. That alos starts the shell as root in the container.

Do you have any specific issue with the user or you are just afraid of using the root user?

Just in case if I was not 100% clear: what you see as root in the container is your non-root suer on the host. Only the name is different and the ID from the container’s point of view, but that is not the real ID. So basically all you could break is your own dev environment. And you can switch to any user that you create in the container as root, but than when you mount files from the host, you will have no access to those files, because if you own the files on the host as your non-root suer, then the root user will own it in the container (since they are the same) and IDs of other users would be larger numbers whihc you would have to figure out (possible) to mount the files properly so that specific user can access it.

Also if you use a non-root user in a container started by rootless Docker, you will not be able to edit the files on the host. When you edit your source code, it is something you want to avoid.

1 Like

I think I felt a bit of an unfounded fear about using the root user, as you mentioned, because I don’t know much about Linux systems and security. Since I’m only using devcontainers on my own machine, it seems like running them as the root user shouldn’t be a big deal.

So, would it also be okay to use the traditional method of adding the user to the docker group for the development host instead of going rootless? Then, would it work to run only the containers for apps as non-root user? I’d like to lay this out in a table like this:

host machine devcontainer app
Physical Location my desktop my desktop dev: my desktop / prod: AWS EC2
OS Ubuntu 24.04 Ubuntu 24.04 Alpine 3.20
Docker root-ful or root-less (either ok) root-less -
User non-root (heston-pablo) root (= heston-pablo) non-root (e.g. app)
Role build and run the image of devcontainer build and run the image of app run app’s code

Is my overall concept correct? If there are any errors or areas for improvement, I’d appreciate your feedback.