Local docker volume with write permission from www-data - docker

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.

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.

Docker does not mount volume as current user

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.

Docker Volume Persistence not working for more than one run of a container

Docker version 20.10.2
I'm just starting out on Docker and following training guides - but something hasn't been mentioned so far (that I have discovered) - when I run a container to write some data out to Docker volume, if I run that container again and attach to the same volume, the newly named data will not append into it ?
Here is my rather basic Dockerfile
FROM ubuntu
RUN mkdir applocal
RUN touch applocal/applocalfile."$(date --iso-8601=seconds)"
RUN ls -la applocal
I run this sequence of commands...
docker build Dockerfile -t mine/applocal-persist
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM ubuntu
---> c29284518f49
Step 2/4 : RUN mkdir applocal
---> Running in 9f796f4d988a
Removing intermediate container 9f796f4d988a
---> 99005a7ffed1
Step 3/4 : RUN touch applocal/applocalfile."$(date --iso-8601=seconds)"
---> Running in ffbf2f4c636a
Removing intermediate container ffbf2f4c636a
---> 199bc706dcc6
Step 4/4 : RUN ls -la applocal
---> Running in 7da02faa9fba
total 8
drwxr-xr-x 1 root root 4096 Jul 16 13:52 .
drwxr-xr-x 1 root root 4096 Jul 16 13:52 ..
-rw-r--r-- 1 root root 0 Jul 16 13:52 applocalfile.2021-07-16T13:52:00+00:00
Removing intermediate container 7da02faa9fba
---> 7387c521d82b
Successfully built 7387c521d82b
Successfully tagged mine/applocal-persist:latest
Then run the command...
docker run -v applocalsaved:/applocal mine/applocal-persist
Looking at the Volume data it has worked
ls -la /var/lib/docker/volumes/applocalsaved/_data/
total 8
drwxr-xr-x 2 root root 4096 Jul 16 14:55 .
drwxr-xr-x 3 root root 4096 Jul 16 14:55 ..
-rw-r--r-- 1 root root 0 Jul 16 14:52 applocalfile.2021-07-16T13:52:00+00:00
If I wait a few minutes later and re-run docker run -v applocalsaved:/applocal mine/applocal-persist
...and check the volume data again, no new file exists
ls -la /var/lib/docker/volumes/applocalsaved/_data/
total 8
drwxr-xr-x 2 root root 4096 Jul 16 14:55 .
drwxr-xr-x 3 root root 4096 Jul 16 14:55 ..
-rw-r--r-- 1 root root 0 Jul 16 14:52 applocalfile.2021-07-16T13:52:00+00:00
Run history...
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6d16e9aa495e mine/applocal-persist "bash" 57 seconds ago Exited (0) 55 seconds ago distracted_cohen
69ff06d9c886 mine/applocal-persist "bash" 2 minutes ago Exited (0) 2 minutes ago affectionate_lehmann
I've listed the Volume Inspect here...
docker volume inspect applocalsaved
[
{
"CreatedAt": "2021-07-16T14:55:24+01:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/applocalsaved/_data",
"Name": "applocalsaved",
"Options": null,
"Scope": "local"
}
]
I'm obviously missing a trick here - or misunderstanding what is going on or the design around this.
Thanks in advance
For info: I'm using Windows running Virtual Box and running Ubuntu 21.04 as a VM
Those commands run once when the image is built.
If you want something to run on container startup, you can use CMD or ENTRYPOINT
https://docs.docker.com/engine/reference/builder/#cmd
https://docs.docker.com/engine/reference/builder/#entrypoint
The commands in the Dockerfile only run once, when the image is originally built. You can verify this for example by just running the image without a volume mount:
docker build -t mine/applocal-persist .
docker run --rm mine/applocal-persist \
ls -l ./applocal
sleep 60
docker run --rm mine/applocal-persist \
ls -l ./applocal
If you start the container with a named volume mounted, only if the volume is a Docker named volume and only if the volume is empty, the contents of the image will be copied into the volume. (This doesn't happen on Docker bind mounts, Kubernetes volumes, or if the image has changed; I would not rely on this for any sort of data sharing since it works in so few contexts.)
Conversely, if you start the container with any sort of volume mounted, whatever content is in the volume completely replaces what's in the image. You can see this with some more experimentation:
# Build the image
docker build -t mine/applocal-persist
# Start the container with a new named volume mounted; see what's there.
docker volume rm applocalsaved
docker run --rm -v applocalsaved:/applocal mine/applocal-persist \
ls -l /applocal
# Edit a file in the volume and see that it gets persisted across restarts
docker run --rm -v applocalsaved:/applocal mine/applocal-persist \
touch /applocal/foo
docker run --rm -v applocalsaved:/applocal mine/applocal-persist \
ls -l /applocal
# But it is not included in the image without the bind mount
docker run --rm mine/applocal-persist \
ls -l /applocal
sleep 60
# Rebuild the image
docker build -t mine/applocal-persist
# In the base image, you will see the updated timestamp
docker run --rm mine/applocal-persist \
ls -l /applocal
# But if you mount the volume, the old volume contents replace the
# image contents and you will only see the old timestamp
docker run --rm -v applocalsaved:/applocal mine/applocal-persist \
ls -l /applocal

Cannot mount directory inside docker container

I can't mount directory. I'm using linux containers on win10.
docker run --rm -v c:\users\pperak:/data alpine ls /data -la
docker run --rm -v /c/users/pperak:/data alpine ls /data -la
ls -la returns
drwxr-xr-x 2 root root 40 Feb 14 15:29 .
drwxr-xr-x 1 root root 4096 Feb 14 15:33 ..
https://docs.docker.com/storage/bind-mounts/ says not to use --volume and use --mount instead
docker run --rm --mount type=bind,source=c:\users\pperak,target=/data alpine ls /data -la
docker run --rm --mount type=bind,source=/c/users/pperak,target=/data alpine ls /data -la
But this also doesn't work.
What am I doing wrong?
After spending half a day on it I reminded myself that I once had similar problem. Some files not visible and other visible as folders after adding Docker volume
(Some files not visible and other visible as folders after adding Docker volume)
It didn't work because I changed password and after you change your password you need to disable sharing drives and enable it again. You will be asked for your password then and it will work again.

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.

Resources