Docker does not mount volume as current user - docker

I have a website that I'm trying to run inside Docker container. To avoid file permission errors, I change the ID of user www-data to match my user id on host. This setup worked for me, but after some time it stopped working, and I cannot find reason why.
FROM php:7.4-fpm
ARG HOST_UID
# Not relevant lines skipped
RUN usermod -u $HOST_UID www-data
RUN groupmod -g $HOST_UID www-data
Then I build container with:
docker compose build --build-arg HOST_UID=$(id -u)
All files on host belong to my user:
After starting container, I can see that ID is changed:
However, inside container they belong to root:
Could this be because docker daemon runs as root and mounts the volume as such?
I should have noted that this Dockerfile installs Supervisord (to run my background scripts), so I cannot run whole container with my user – this fixes permissions but nothing can be installed inside container.

You should use the -u flag for docker compose run.
Here an example:
setup:
mkdir mihai
touch mihai/test.txt
docker-compose.yml
version: '3'
services:
test:
image: "alpine:latest"
volumes:
- "./mihai:/mihai"
Run normal
docker compose run test ls -l /mihai
gives output:
total 0
-rw-r--r-- 1 root root 0 Sep 18 11:39 test.txt
Run as user:
docker compose run -u "$(id -u):$(id -g)" test ls -l /mihai
gives output:
total 0
-rw-r--r-- 1 501 dialout 0 Sep 18 11:39 test.txt
If you use a custom image where you actually declare user and group then you will see a nicer output than 501 and dialout.

Related

Rootless Docker: Need to provide write access to a non-root user in docker container for a volume mounted on the host

I want to provide write access to a non-root user in a docker container for a volume mounted on the host. I have the same non-root user and group inside container and host as well.
While running the container, I mount a host volume to it -v /some/folder:/some/folder. I am doing this because my application running inside the docker container needs to write files to the mounted host folder. But since I am running my application as a non-root user, it doesn’t have permission to write to that folder.
Also, I this mounted folder permission is got changed inside the container automatically.
I have given assigned below user and group as an owner to this folder on the host:
“nonrootuser1:nonrootgroup1”
For 'rootful' docker it works fine, but if it's rootless inside the container it is showing below user and group as an owner to this folder:
“root:nobody”
Steps to reproduce this:
Add user and group on the host
groupadd -g 1015 nonrootgroup1
useradd -u 1099 nonrootuser1
Create dir which will be assigned to osquery groupadd on the host:
sudo su
mkdir -p /var/osquery/sock
echo "hello world" > /var/osquery/sock/file.txt
chown root:nonrootgroup1 /var/osquery/sock
chmod g+s /var/osquery/sock/
Create Dockerfile in the home directory :
FROM alpine:3.14
RUN addgroup -g 1015 -S nonrootgroup1
RUN adduser -D nonrootuser1 -u 1099
USER nonrootuser1:nonrootgroup1
CMD ["tail", "-f", "/dev/null"]
Run docker container :
docker run --rm -d --name sample-app -v /var/osquery/sock:/var/osquery/sock $(docker build . -q)
Check the user id of the container :
dmytro#dmytro:~/dev/sample-image$ docker exec sample-app id
uid=1099(nonrootuser1) gid=1015(nonrootgroup1) groups=1015(nonrootgroup1)
check the permissions to the /var/osquery/sock dir inside the container :
Directory /var/osquery/sock is assigned to group 'nobody' instead of 'nonrootgroup1' group
dmytro#dmytro:~/dev/sample-image$ docker exec sample-app ls -lah /var/osquery
total 12K
drwxr-xr-x 3 root root 4.0K Dec 28 10:47 .
drwxr-xr-x 1 root root 4.0K Dec 28 10:47 ..
drwxr-s--- 2 nobody nobody 4.0K Dec 28 09:34 sock
Host details are mentioned below:
Kernel Version: 5.4.0-135-generic
Operating System: Ubuntu 20.04.5 LTS
Storage Driver: overlay2
Please suggest.
Thanks!
I tried to setup in the daemon.json "userns-remap" config, but docker daemon doesn't start with it, because it lacks permission to create dockremap user and group.

How to user docker compose volumes do reflect container file on the host when running the container process with user that only exist on the container

I don't make that much experience with containers and bash script also and I am having a really hard time trying to make a directory on my host machine copy the log files from a celery container. I run docker on rootless mode.
I have a dockerfile where I create a user and group named "celery", install gosu and define a entrypoint and a cmd. On the entry point I simple exec gosu "$USER_NAME" "$#" and the CMD is
celery \
-A src.core.celery_app \
worker \
--pool=gevent \
--concurrency=5 \
--loglevel=info \
--pidfile=/var/run/celery/%n.pid \
--logfile=/var/log/celery/%n%I.log
If I run the docker compose without volumes everything works fine: I have the worker running on the container under the celery user and also the /var/log/celery/celery.log owned by celery celery.
# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
celery 1 0.0 0.0 2420 596 ? Ss 10:42 0:00 /bin/sh ./start-celeryworker
celery 12 0.8 0.5 210872 84496 ? Sl 10:42 0:01 /usr/local/bin/python /usr/local/bin/celery -A src.core...
# ls -la /var/log
total 752
drwxr-xr-x 1 celery celery 4096 Jun 24 10:42 celery
But if I try to add a volume so I can have the log files on the host volumes: <local dir>:/var/log/celery the local dir is created, but it is empty and I get a permission denied error:
File "/usr/local/lib/python3.9/logging/__init__.py", line 1175, in _open
return open(self.baseFilename, self.mode, encoding=self.encoding,
PermissionError: [Errno 13] Permission denied: '/var/log/celery/celery.log'
I even tried chmod 777 on the container file, but still get the error. I looked at the postgres official image dockerfile and entrypoint.sh, and how is the file structure of the postgres container after build (because there I can get the pgdata directory on the host under user 100069 and group jap(this is my user name - uid:gid 1000:1000)), but as I mentioned before, I don't have that much knowledge of bash.
I gave uid and gid 1003 for the celery user and group on the container and on the host the process run under 101002.
Now, if I don't create the "celery" user and group and run celery as root everything works perfectly and I the volume works too. Any ideas? tks

Can't change ownership of '/dev/gpiomem' in a docker container in RPi

I'm trying to run a simple docker container with a python base image to control the LEDs on my RPi4.
The Dockerfile compiles fine and I'm running it as follows:
docker run --rm -ti --privileged --device /dev/gpiomem:/dev/gpiomem -d led_blinker bash
Once inside the docker container I run a ls -l /dev/gpiomem and I get
root#ca1506d00cc5:/# ls -l /dev/gpiomem
crw-rw---- 1 nobody nogroup 246, 0 Dec 30 21:47 /dev/gpiomem
I try to do
root#ca1506d00cc5:/# chown root.root /dev/gpiomem
chown: changing ownership of 'dev/gpiomem': Operation not permitted
But when I run a whoami I get I'm the root user. What is that I'm missing?
PS. I have also added the flag --user root and got the same results.

Local docker volume with write permission from www-data

Here is part of my Dockerfile :
RUN mkdir /data
RUN chown www-data:www-data /data
RUN chmod 664 /data
VOLUME ["/data"]
I create the image with the command :
docker build -t webapp .
I run it like this :
docker run -d -p 80:80 -v /home/user/data:/data webapp
But in my host user dir, the data directory is created like this :
drwxr-xr-x 2 root root 4,0K avril 28 21:52 data
And in the image (docker exec -it CONTAINER_ID bash) i have :
drwxr-xr-x 2 root root 4096 Apr 28 19:52 data
So commands are ignored from the Dockerfile.
How can a web docker app simply get permission to write on a host directory ?
So you are building an image, setting chmods, and it's all cool.
But then you run the container with -v option, which means /data will be replaced with mounted volume. At this time all files and permissions from built image are ignored. You can check this by running container without -v option. The solution is to create entrypoint script (with ENTRYPOINT or CMD command in Dockerfile) which will first fix permissions and then run original command for your image.

write in shared volumes docker

I have a docker with a php application on it
I have a share volume, for example
/home/me/dev/site <=> /var/www/site
I can write something in my host, it will be sync with the container
if I launch
sudo docker exec test touch /var/www/site/test.txt
It works
But if my server is trying to create a file as www-data this is not working because of the rights.
Is there a way to give access to my shared volumes to www-data ?
I am using boot2docker
(Bind-mounted) volumes in Docker will maintain the permissions that are set on
the Docker host itself. You can use this to set the permissions on those
files and directories before using them in the container.
Some background;
Permissions in Linux are based on user and group ids ('uid' / 'gid'). Even
though you see a user- and group name as owner, those names aren't actually
important in Linux, they are only there to make it easier for you to see who's the owner of a file (they are looked up from the /etc/passwd file).
You can set any uid/gid on a file; a user doesn't have to exist when setting those permissions. For example;
touch foobar && sudo chown 1234:5678 foobar && ls -la foobar
# UID and GID are set to 1234 / 5678, even though there's no such user
-rw-rw-r-- 1 1234 5678 0 Mar 25 19:14 foobar
Checking permissions (inside and outside a container)
As mentioned above, Docker maintains ownership of the host when using
a volume. This example shows that permissions and ownership in the volume are the
same outside and inside a container;
# (First create a dummy site)
mkdir -p volume-example/site && cd volume-example
echo "<html><body>hello world</body></html>" > site/index.html
# Permissions on the Docker host;
ls -n site
# total 4
# -rw-rw-r-- 1 1002 1002 38 Mar 25 19:15 index.html
# And, permissions inside a nginx container, using it as volume;
sudo docker run --rm -v $(pwd)/site:/var/www nginx ls -n /var/www
# total 4
# -rw-rw-r-- 1 1002 1002 38 Mar 25 19:15 index.html
Setting the permissions
As explained, a user doesn't have to exist in order to use them, so even if
we don't have a www-data user on the Docker host, we can still set the correct
permissions if we know the "uid" and "gid" of that user inside the container;
Let's see what the uid and gid of the www-data user is inside the container;
sudo docker run --rm nginx id www-data
# uid=33(www-data) gid=33(www-data) groups=33(www-data)
First check the state before changing the permissions. This time we
run the nginx container as user www-data;
sudo docker run \
--rm \
--volume $(pwd)/site:/var/www \
--user www-data nginx touch /var/www/can-i-write.txt
# touch: cannot touch `/var/www/can-i-write.txt': Permission denied
Next, set the permissions on the local directory, and see if we are able to write;
sudo chown -R 33:33 site
sudo docker run \
--rm \
--volume $(pwd)/site:/var/www \
--user www-data nginx touch /var/www/can-i-write.txt
Success!
Add the following lines to your dockerfile and rebuild your image
RUN usermod -u 1000 www-data
RUN usermod -G staff www-data

Resources