prevent changing of permissions in mounts with rootless container - docker

In rootful containers, the solution to this problem is run with --user "$(id -u):$(id -g)" however this does not work for rootless contain systems (rootless docker, or in my case podman):
$ mkdir x
$ podman run --user "$(id -u):$(id -g)" -v "$PWD/x:/x:rw" ubuntu:focal bash -c 'echo hi >> /x/test'
bash: /x/test: Permission denied
so for rootless container systems I should remove --user since the root user is automatically mapped to the calling user:
$ podman run -v "$PWD/x:/x:rw" ubuntu:focal bash -c 'echo hi >> /x/test'
$ ls -al x
total 12
drwxr-xr-x 2 asottile asottile 4096 Sep 3 10:02 .
drwxrwxrwt 18 root root 4096 Sep 3 10:01 ..
-rw-r--r-- 1 asottile asottile 3 Sep 3 10:02 test
but, because this is now the root user, they can change the ownership to users which are undeleteable outside container:
$ podman run -v "$PWD/x:/x:rw" ubuntu:focal bash -c 'mkdir -p /x/1/2/3 && chown -R nobody /x/1'
$ ls -al x/
total 16
drwxr-xr-x 3 asottile asottile 4096 Sep 3 10:03 .
drwxrwxrwt 18 root root 4096 Sep 3 10:01 ..
drwxr-xr-x 3 165533 asottile 4096 Sep 3 10:03 1
-rw-r--r-- 1 asottile asottile 3 Sep 3 10:02 test
$ rm -rf x/
rm: cannot remove 'x/1/2/3': Permission denied
so my question is: how do I allow writes to a mount, but prevent changing ownership for rootless containers?

I think --user $(id -u):$(id -g) --userns=keep-id will get what you want.
$ id -un
erik
$ id -gn
erik
$ mkdir x
$ podman run -v "$PWD/x:/x:Z" --user $(id -u):$(id -g) --userns=keep-id docker.io/library/ubuntu:focal bash -c 'mkdir -p /x/1/2/3 && chown -R nobody /x/1'
chown: changing ownership of '/x/1/2/3': Operation not permitted
chown: changing ownership of '/x/1/2': Operation not permitted
chown: changing ownership of '/x/1': Operation not permitted
$ ls x
1
$ ls -l x
total 0
drwxr-xr-x. 3 erik erik 15 Sep 6 19:34 1
$ ls -l x/1
total 0
drwxr-xr-x. 3 erik erik 15 Sep 6 19:34 2
$ ls -l x/1/2
total 0
drwxr-xr-x. 2 erik erik 6 Sep 6 19:34 3
$
Regarding deleting files and directories that are not owned by your normal UID and GID (but from the extra ranges in /etc/subuid and /etc/subgid) , you could
use podman unshare rm filepath
and podman unshare rm -rf directorypath

Related

Docker volume mount giving root ownership of parent directory

I am using a docker and mounting something into the /home/(user) directory on the docker image using
-v ~/.aws:/home/$(shell id -nu)/.aws. The issue is, since /home/(user) did not exist prior to creating the docker, /home/(user) ends up being owned by root. This is causing issues for pip, sam-cli, etc because they are all attempting to store some information in the user home directory.
How can I avoid this situation without completely abandoning using a specific user? I've tried using chown to change the ownership, but I always get 'Operation not Permitted.'
Pretty easy to reproduce
developer#desktopimage:~/AWS$ docker run --rm -it -v ~/.aws:/home/developer/.aws -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro -u 1001:1001 alpine:latest ls -al /home/developer
total 12
drwxr-xr-x 3 root root 4096 Feb 25 14:09 .
drwxr-xr-x 1 root root 4096 Feb 25 14:09 ..
drwxr-xr-x 5 develope develope 4096 Feb 3 20:49 .aws
developer#desktopimage:~/AWS$ docker run --rm -it -v ~/.aws:/home/developer/.aws -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro -u 1001:1001 alpine:latest ls -al /home
total 12
drwxr-xr-x 1 root root 4096 Feb 25 14:09 .
drwxr-xr-x 1 root root 4096 Feb 25 14:09 ..
drwxr-xr-x 3 root root 4096 Feb 25 14:09 developer

Docker Why are permissions wrong after bind mount?

I'm mounting my hosts /tmp/docker to /home/vault/tmp/ in my container but the user vault in my container does not have write permissions even though on my host, /tmp/docker is set to 777 and the uid and gid values are set to the same in the host & the container too. How can I fix this and make sure that my user vault has write/owner permissions?
HOST
$ ls -la /tmp/docker/
total 8
drwxrwxrwx 2 ron ron 4096 Feb 5 19:34 .
drwxrwxrwt 12 root root 4096 Feb 13 09:49 ..
ron#ENGDEV:~/novax-prs/docker$ id -u; id -g
1003
1003
GUEST
$ ls -la /home/vault/tmp/
total 8
drwxr-xr-x 2 root root 4096 Feb 13 06:47 .
drwxr-xr-x 1 vault vault 4096 Feb 13 18:06 ..
vault#novax_prs_build:~$ id -u; id -g
1003
1003
bind mount
docker run -it \
-e LOCAL_USER_ID=`id -u` \
--user "$(id -u):$(id -g)" \
-v ${dir}:/home/vault/ccimx6ulstarter \
-v /tmp/docker:/home/vault/tmp:Z \
${name}
funny enough, the /home/vault/ccimx6ulstarter/ directory has user the permissions set correctly in the container.
Your /tmp folder probably uses tmpfs which behaves differently than for example ext4, especially when it comes to SELinux labeling (with the :Z option).
Try using a folder which lies on an ext4 filesystem.
created a ~/tmp_docker/ in the host user's home directory and bind mounted that with -v, got the correct permissions in the container and will use this and can use this as ~/tmp/ in my container!
Saying this, I'm not sure why my host's /tmp/docker/ would not bind with the correct permissions.

Permission denied when get contents generated by a docker container on the local fileystem

I use the following command to run a container:
docker run -it -v /home/:/usr/ ubuntu64 /bin/bash
Then I run a program in the container, the program generates some files in the folder:/usr/ which also appear in /home/ but I can't access the generated files with an error: Permission denied outside the container.
I think this may because the files generated by root in the container but outside the container, the user have no root authority, but how to solve it?
What I want to do is accessing the files generated by the program(installed in the container) outside the container.
You need to use the -u flag
docker run -it -v $PWD:/data -w /data alpine touch nouser.txt
docker run -u `id -u` -it -v $PWD:/data -w /data alpine touch onlyuser.txt
docker run -u `id -u`:`id -g` -it -v $PWD:/data -w /data alpine touch usergroup.txt
Now if you do ls -alh on the host system
$ ls -alh
total 8.0K
drwxrwxr-x 2 vagrant vagrant 4.0K Sep 9 05:22 .
drwxrwxr-x 30 vagrant vagrant 4.0K Sep 9 05:19 ..
-rw-r--r-- 1 root root 0 Sep 9 05:21 nouser.txt
-rw-r--r-- 1 vagrant root 0 Sep 9 05:21 onlyuser.txt
-rw-r--r-- 1 vagrant vagrant 0 Sep 9 05:22 usergroup.txt

Mount "named volume" as non-root in Docker

Is there any way to mount a named volume as a non-root user? I am trying to avoid having to run a chown in each Dockerfile but I need the mount to be writable by a non-root user to be able to write the artifacts created by a build in the image
This is what I'm trying
docker run --rm -it -v /home/bob/dev/:/src/dev -v builds:/mnt/build --name build hilikus/build /bin/bash
but for the second mount I get
[user#42f237282128 ~]$ ll /mnt
total 4
drwxr-xr-x 2 root root 4096 Sep 18 19:29 build
My other mount (/src/dev/) is owned by user, not by root so it gives what I need; however, I haven't been able to do the same with the named volume.
The named volume initializes to the contents of your image at that location, so you need to set the permissions inside your Dockerfile:
$ cat df.vf-uid
FROM busybox
RUN mkdir -p /data && echo "hello world" > /data/hello && chown -R 1000 /data
$ docker build -t test-vf -f df.vf-uid .
Sending build context to Docker daemon 23.06 MB
Step 1 : FROM busybox
---> 2b8fd9751c4c
Step 2 : RUN mkdir -p /data && echo "hello world" > /data/hello && chown -R 1000 /data
---> Using cache
---> 41390b132940
Successfully built 41390b132940
$ docker run -v test-vol:/data --rm -it test-vf ls -alR /data
/data:
total 12
drwxr-xr-x 2 1000 root 4096 Sep 19 15:26 .
drwxr-xr-x 19 root root 4096 Sep 19 15:26 ..
-rw-r--r-- 1 1000 root 12 Aug 22 11:43 hello
If you use the new --mount syntax instead of the old -v/--volume syntax it is supposedly possible to assign a uid to the volume's contents via docker volume create somename --opt -o=uid=1000 or something similar.
See https://docs.docker.com/engine/reference/commandline/volume_create/#driver-specific-options
I haven't fully tested this to run as non-root or using the dockremap dynamic user with the userns-map option but hope to soon.

How to read and write to mounted volume without running as root?

When mounting a volume with the following command:
docker run -t -i --volumes-from FOO BAR
the volumes from FOO are mounted with root as owner. I can't read and write to that without running as root as far as I know. Must I run as root or is there some other way?
I have tried by creating the folder with other owner before mounting but the mounting seems to overwrite that.
Edit: A chown would work if it could be done automatically after the mounting somehow.
I'm not sure why you aren't able to change your folder permissions in your source image. This works without issue in my lab:
$ cat df.vf-uid
FROM busybox
RUN mkdir -p /data && echo "hello world" > /data/hello && chown -R 1000 /data
$ docker build -f df.vf-uid -t test-vf-uid .
...
Successfully built 41390b132940
$ docker create --name test-vf-uid -v /data test-vf-uid
e12df8f84a3b1f113ad5440b62552b40c4fd86f99eec44698af9163a7b960727
$ docker run --volumes-from test-vf-uid -u 1000 -it --rm busybox /bin/sh
/ $ ls -al /data
total 12
drwxr-xr-x 2 1000 root 4096 Aug 22 11:44 .
drwxr-xr-x 19 root root 4096 Aug 22 11:45 ..
-rw-r--r-- 1 1000 root 12 Aug 22 11:43 hello
/ $ echo "success" >/data/world
/ $ ls -al /data
total 16
drwxr-xr-x 2 1000 root 4096 Aug 22 11:46 .
drwxr-xr-x 19 root root 4096 Aug 22 11:45 ..
-rw-r--r-- 1 1000 root 12 Aug 22 11:43 hello
-rw-r--r-- 1 1000 root 8 Aug 22 11:46 world
/ $ cat /data/hello /data/world
hello world
success
/ $ exit
So, what I ended up doing was mounting the volume to another container and change the owner (using uid of the owner I wanted in the final setup) from that container. Apparently uid's are uid's regardless. This means that I can run without being root in the final container. Perhaps there are easier ways to do it but this seems to work at least. Something like this: (untested code clip from my final solution)
docker run -v /opt/app --name Foo ubuntu /bin/bash
docker run --rm --volumes-from Foo -v $(pwd):/FOO ubuntu bash -c "chown -R 9999 /opt/app"
docker run -t -i --volumes-from FOO BAR

Resources