Need solution for running dev container with rootless Docker
Writing to the host filesystem fails unless the container is run with root privileges.
Steps to Reproduce:
- Set up rootless Docker environment (dockerd-rootless-setuptool.sh install)
- Start a development container (docker run ...)
- Attempt to write files from the container to the host filesystem (echo "test" > /host/path/file.txt)
Expected Behavior: Files should be written successfully to the host filesystem without needing to run the container as root.
Did you try to alter file permissions? Like using chmod?
To write files from a rootless Docker container to the host filesystem, you need to ensure that the user inside the container has the necessary permissions to write to the specified directory on the host. Here are the steps to achieve this:
- Ensure Correct User Mapping: When running Docker in rootless mode, the user inside the container is mapped to a user on the host. Ensure that the user inside the container has the same UID and GID as the user on the host who has write permissions to the target directory.
- Set Up Permissions on the Host: Ensure that the target directory on the host has the appropriate permissions to allow writing by the user mapped from the container.
- Run the Container with the Correct User: Use the --user flag to specify the UID and GID when running the container.
@jcr010910 Which image are you using? The images hosted from https://github.com/devcontainers/images have ^ configured to support rootless docker.
From inside the dev container, it appears as if the 'vscode' user has the same id as the host user (1000).
However the actual user id, when mapped to the host, was (100999).
So you can work around this, as a hack, with chmod o+w.
I don't think this statement is correct...
The images hosted from https://github.com/devcontainers/images have configured to support rootless docker.
Note: Rootless Docker is not the same thing as a container-internal non-root user.
Hello, I have a suggestion, unsure if it should be implemented as a feature or as what actually but will solve the problem. It's just a bit tricky to describe and might be hard to say how to implement it so that it works no matter what kind of docker we are running on, whether rootful, rootless or rootful with userns remap. There is an ability to create so called idmapped mounts. You can bind mount something in a way so that it has a different uid/gid in the mount than in original place. The problem is that the relevant option in mount command is very new and buggy. it's not even present on ubuntu images. That said, it can still be done, would be useful if devcontainer tools would do it automatically for at least some things, for example for the workspace folder. I will describe how it's supposed to work. Of course needs a pretty recent kernel, but same as some other features of docker rootless including overlay2.
The idea is to bind mount the workspace folder to itself so that even though it's owned by user from the host, which is visible as root of container, it will suddenly start being visible as the container user for example. First requirement is to add the CAP_SYS_ADMIN to that container, which in user namespace should be safe enough, but would be less so in root containers. Then, everything is done inside container, not outside of it, before switching to the container user if possible (still as root). Assuming we have a mounted workspace in /workspace and we want to use container user ubuntu (uid 1000) with primary group ubuntu (gid 1000): What we want is something like this assuming mount has needed options which work instead of being buggy:
mount -o X-mount.idmap=b:0:1000:1,bind /workspace /workspace
When that works, then suddenly doing ls -ld /workspace will magically show it owned as user ubuntu/group ubuntu. Note this procedure kind of assumes folder is owned only by one user at a time, othervise other users get mapped to a high uid.
This procedure works when the initial owner is not 0 (container root), just change 0 to the other uid. in fact if it's 1000 on both sides it shouldn't be a problem.
Now what it's actually doing, needed mostly because mount is either buggy when using the above option or doesn't have it at all, probably the latter. But has a variation of this option taking a file... Idmapped mounts are based on user namespaces. Basically a container runtime should create the user namespace (which it does for each container) and pass it over when mounting, and that makes the mount be remapped to user namespace without having to manually chown. This can be exploited to do custom mappings by:
- Creating the user namespace and holding it for a while,
- Mapping user uid 0/gid 0 (or another user who is an original workspace owner) from inside user namespace to the unprivileged user outside (uid 1000/ubuntu in this case),
- Bind mounting like above, but passing in the user namespace file. This will make all files in workspace vievable as user 1000 when seen through the new mount, and user namespace can be destroyed after. This can be done probably using a combination of unshare and mount, where unshare is called just to create user namespace, perform mappings and hold namespace for enough time to be able to run mount on it. This should be supported everywhere.
on another note however, root in a rootless container in docker by default doesn't have most capabilities which makes it pretty safe to use. If you dropped them all it would be perfectly equivalent to your host user, using unprivileged user just makes it harder to destroy a container from inside and makes it unable to access non idmapped user directories which were not world accessible before.