Docker mount volume directory permissions to non root user using dockerfile - linux

I have a dockerfile with an entrypoint that starts a java app jar in shell process.I have set USER nobody in dockerfile before entrypoint to make sure the entrypoint shell is executed by nobody user and not root. The task definition for the container on AWS ECS takes care of the volume and mount parameters. So ideally at container run time /var/log/applogs on host is mounted onto the container with same path. But what happens is that since the user context is switched from root to nobody, so nobody that runs the container (executing the entrypoint) doesn’t have write permission to /var/log/applogs/ directory on the container. As such the app is unable to create the log file there on the container.
What i see is that the host ec2 /var/log/applogs gets mounted just fine on the container being run by nobody user but since the nobody user is missing write permissions on this path on the container, hence its unable to write app log here.
What is the correct way to fix this either on the dockerfile or something else?

You can try this...
Remove the USER nobody entry from Dockerfile and change your
Entrypoint into the following script:
#!/bin/bash
# change ownership to user=nobody, group=nobody
chown -R nobody:nobody /var/log/applogs
# open with sudo a new shell as user nobody and call your application
sudo -u nobody /bin/bash -c "java -jar /path/to/your/application.jar"
# alternative
# open with su a new shell as user nobody and call your application
# su -s /bin/bash -c "java -jar /path/to/your/application.jar" nobody

Related

how to execute root command inside non-root process running inside docker container

I have a docker container running which start up few daemon processes post run with normal user (say with non-root privileges) id. The process which was running with normal user has to create some files and directories under /dev inside the container by calling python function which executes os.system('mkdir -p /dev/some_dir') calls. However when run, these calls are failing without the directory being created. But I can run those cmds from container bash prompt where my id is uid=0(root) gid=0(root) groups=0(root).
Even providing sudo before the cmd inside os.system('sudo mkdir -p /dev/some_dir') is not working.
Is there any way I can make it work. I can not run the process with root user id due to security implications, but I need to create this directory as well.
thanks for your pointers
You should give /dev directory a permission to write files for your non-root user.

Docker "permission denied" in container

I am trying to run a docker image by
docker run -it -v $PWD/examples:/home/user/examples image
which should make $PWD/examples in the host accessible in the container. However when I ls in the container, it keeps giving me
ls: cannot access 'examples': Permission denied
I have tried the answers for similar questions, the z/Z option and chcon -Rt svirt_sandbox_file_t /host/path/ and run --privileged, but neither of them have any effect in my case.
In fact, the z option appears to work for the first time ls, but when I issue ls the second time it is denied again.
In the comments it turned out that there is probably a USER instruction in the Dockerfile of the image. This user is not allowed to access examples due to file access permissions of examples.
It is possible to supersede USER with docker run option --user.
A quick and dirty solution is to run with --user=root to allow arbitrary access.
Be aware that files written as root in container to folder examples will be owned by root.
A better solution is to look for owner of examples, call him foo. Specify its user id and group id to have exactly the same user in container:
docker run --user $(id -u foo):$(id -g foo) imagename
Another possible solution is to allow arbitray access with chmod 666 examples or chmod 644 examples, but most probably you don't want that.
The best way would be to look at the Dockerfile and check the purpose of USER instruction.
If it only serves the purpose of avoiding root in container, the best way is to use --user=foo or more precisely --user=$(id -u foo):$(id -g foo).
If something in Dockerfile/image relies on specific USER, it may be the best to change access permissions of examples.
If you have access to the Dockerfile, you may adjust it to fit your host user/the owner of examples.
Try running the container as privileged:
sudo docker run --privileged=true -itd -v /***/***:/*** ubuntu bash
for example: sudo docker run --privileged=true -itd -v
/home/willie:/wille ubuntu bash

File permissions in Docker Container

I have a simple tomcat docker file as below.
FROM tomcat:7
MAINTAINER ***
COPY sample.war /opt/tomcat/webapps
USER tomcat
RUN chown -R tomcat:tomcat /tmp/
CMD ["catalina.sh", "run"]
When i create the docker image it will give me file permission as
tomcat tomcat Dec 11 08:04 tmp
My sample app creates few directories inside tmp folder , i am expecting the owner to be tomcat but it looks like root. Since i am running the container as user tomcat , how to make it use tomcat user to create these.
I tried to build and run the Dockerfile you provided and ran into multiple errors. You are asking about the file permissions your "app" creates. So here is my starting point:
I assume that the "app" is catalina.sh. The process which creates your files in /tmp/. Since we are running the container as the user tomcat it automatically creates the files with the according file permissions. Have a look at the code comments below to get some more information about what is going on here.
Dockerfile:
FROM httpd
# I switched the image since you would need to configure tomcat to make it run
# httpd works out of the box without any application specific config. That's why
COPY ./catalina.sh /
RUN chmod +x /catalina.sh # copy your 'app' / entrypoint into the image
RUN groupadd -r tomcat \
&& useradd -r -g tomcat tomcat
# create a new user and group under which the container runs
RUN chown -R tomcat:tomcat /tmp/ # change initial file permisisons.
# So that our new user tomcat is allowed to access and fill the directory with files
USER tomcat # switch the user under which the container runs
ENTRYPOINT ["/catalina.sh"]
catalina.sh:
#!/bin/bash
mkdir /tmp/test # create a dir
touch /tmp/yolo.txt # and some files
touch /tmp/test/yolo2.txt # to check the file permissions later on
while true; do echo "sleep"; sleep 2; done
# endless loop so that the container doesn't exit
To check the file permissions exec into the running container.
docker exec -ti <container_name> bash
Docker normally runs with root privilege, so I believe you must create a docker group (if it does not exist), and add the user (tomcat, in your case) to docker group.
See below how to add user to docker group:
Create the docker group.
$ sudo groupadd docker
Add your user to the docker group.
$ sudo usermod -aG docker tomcat
Reference: https://docs.docker.com/engine/installation/linux/linux-postinstall/#manage-docker-as-a-non-root-user
With this, I believe your problem can be solved.

How to give non-root user in Docker container access to a volume mounted on the host

I am running my application in a Docker container as a non-root user. I did this since it is one of the best practices. However, 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
Question
Is it possible to give a nonroot user in a docker container access to the hosted volume?
If not, is my only option to run the process in docker container as root?
There's no magic solution here: permissions inside docker are managed the same as permissions without docker. You need to run the appropriate chown and chmod commands to change the permissions of the directory.
One solution is to have your container run as root and use an ENTRYPOINT script to make the appropriate permission changes, and then your CMD as an unprivileged user. For example, put the following in entrypoint.sh:
#!/bin/sh
chown -R appuser:appgroup /path/to/volume
exec runuser -u appuser "$#"
This assumes you have the runuser command available. You can accomplish pretty much the same thing using sudo instead.
Use the above script by including an ENTRYPOINT directive in your Dockerfile:
FROM baseimage
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/bin/sh", "entrypoint.sh"]
CMD ["/usr/bin/myapp"]
This will start the container with:
/bin/sh entrypoint.sh /usr/bin/myapp
The entrypoint script will make the required permissions changes, then run /usr/bin/myapp as appuser.
There will throw error if host env don't have appuser or appgroup, so better to use a User ID instead of user name:
inside your container, run
appuser$ id
This will show:
uid=1000(appuser) gid=1000(appuser) groups=1000(appuser)
From host env, run:
mkdir -p /some/folder
chown -R 1000:1000 /some/folder
docker run -v /some/folder:/some/folder [your_container]
inside your container, check
ls -lh
to see the user and group name, if it's not root, then it's should worked.
In the specific situation of using an image built from a custom Dockerfile, you can do the following (using example commands for a debian image):
FROM baseimage
...
RUN useradd --create-home appuser
USER appuser
RUN mkdir /home/appuser/my_volume
...
Then mount the volume using
-v /some/folder:/home/appuser/my_volume
Now appuser has write permissions to the volume as it's in their home directory. If the volume has to be mounted outside of their home directory, you can create it and assign appuser write permissions as an extra step within the Dockerfile.
I found it easiest to recursively apply Linux ACL (Access Control Lists) permissions on the host directory so the non root host user can access volume contents.
sudo setfacl -m u:$(id -u):rwx -R /some/folder
To check who has access to the folder:
getfacl /some/folder
Writing to the volume will create files and directories with host user id which might not be desirable for host -> container transfer. Writing can be disabled with just giving :rx permission instead of :rwx.
To enable writing, add a mirror ACL policy in a container allowing container user id full access to volume parent path.

Docker: Permissions for a mounted volume

I have this image in which I mount a volume from the host
-v /Users/john/workspace:/data/workspace
Inside the container I'm using a user different than root. Now the problem is that it cannot create/modify files inside /data/workspace (permission denied). Now I solved it for now to do chmod -R 777 workspace on the host. What would be the docker way to solve this ?
This might be solved with user mapping (issue 7198), but that same thread include:
Managed to solve this using the new dockerfile args. It doesn't require doing anything special after the container is built, so I thought I'd share. (Requires Docker 1.9)
In the Dockerfile:
# Setup User to match Host User, and give superuser permissions
ARG USER_ID=0
RUN useradd code_executor -u ${USER_ID} -g sudo
RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER ${USER_ID}
Then to build:
docker build --build-arg USER_ID=$(id -u)
That way, the user in the container can write in the mounted host volume (no chown/chmod required)

Resources