How to give docker container write/chmod permissions on mapped volume? - docker

I have a synology NAS which has docker support and wanted to run some docker containers (I'm pretty new to Docker) on it. For example pocketmine-pm (but I believe I have the write issue also with other containers).
I created a volume on the host and mapped this in the container settings. (And in the synology docker settings for the volume mapping I did not click on "read only").
According to the Dockerfile a new user 'pocketmine' is created inside the container and this user is used to start the server. The user seems to have the user ID 1000 (first UID for new linux users). The container also uses an Entrypoint.sh script to start the server.
Initially the container was not able to write files to the mapped directory. I had to SSH into the host 'chown' the directory for the UID 1000:
sudo chown 1000:1000 /volXy/docker/pocketminemp -R
After that the archive could be downloaded and extracted.
Unfortunately I was not able to connect to the server from my iOS device. The server is listed as 'online' but the connection fails without any specific message. I then checked the logs of the container and saw the following entries (not sure if this really prevents the connection but I will give it a try):
[*] Everything done! Run ./start.sh to start PocketMine-MP
chown: changing ownership of '/pocketmine/entrypoint.sh': Operation not permitted
chown: changing ownership of '/pocketmine/server.properties.original': Operation not permitted
Loading pocketmine.yml...
Apparently the container cannot chown a file it was previously able to download.
Does anybody know what can be done to fix this? Do I need to chmod the mapped volume and why did I need to chown the directory to UID 1000 (a user that doesn't really exist on the host) - isn't there a more elegant way to fix the permissions?

When you run the container, you should be able to use the --user="uid:gid" flag to specify the user you wish to run the container as.
Source: https://docs.docker.com/engine/reference/run/#user

Related

How to securely add an entry into a docker container's /etc/passwd for the uid set with docker's --user option

Problem
For a docker image (alpine based) that is supposed to run as non-root I have two requirements:
I have to mount a FUSE filesystem inside the docker container
The users of the docker image are able to set the UID/GID of the docker
user with docker run --user {uid}:{gid}
FUSE's fusermount command requires a valid entry for the user in /etc/passwd, otherwise it won't mount the filesystem. Given that I don't know the the UID/GID of the user at build time I can't call adduser at build time. And I can't do it at runtime either, as the user then doesn't have the appropriate privileges.
Solutions found
So far I have found two solutions that both feel not appropriate/secure
1. Make /etc/passwd writable
When adding chmod 555 /etc/passwd to the Dockerfile I can then do at runtime
echo "someuser:x:${my_uid}:$(id -g)::/tmp:/sbin/nologin" >> /etc/passwd
This does the job for fusermount. Unfortunately I did not find a way to make change the passwd file back to read-only at runtime and without that I have security concerns that someone might be able to misuse this to gain root rights back. While I could not find a simple way to use the open passwd file for some exploit (while I was able to add/modify password & configurations directly in /etc/passwd for all users and then change users via login, alpine did not allow this for user root (neither via login nor via su). But I guess there are folk out there more clever than me, and somehow the whole solution feels like a quite dirty hack. Does anyone have specific ideas how a writeable passwd file inside a container could be used for getting inappropriate rights inside the container?
2. Replace requirement #2 with two additional environment variables
By introducing DUID and DGID as environment variables and set USER to some newly added non-root user inside the Dockerfile I found a solution with the help of sudo & /etc/sudoers: In a launch script that I use as entrypoint I can call sudo adduser/addgroup for the given DUID/DGID and then launch the actual program with the user specified via sudo -u someuser someprog.
Except for the fact that the whole setup became quite ugly, I disliked the fact the user's of my docker image could no longer use the regular docker run --user option, as this would break the sudo configuration.

Docker container volumes are not working as expected

Actually, I am trying to run the below following command
docker run -it --rm -v $(pwd):/var/www/html --user node node:12.13.1-alpine ash.
Expected result
The files inside the container (i.e /var/www/html ) should have user as node.
Actual result
But, the files inside the containers are showing the same user as of the host.
Also, can't create a directory inside the container.
It is working for my other colleagues. So, any help in this would be much appreciated.
Many thanks,
Alwin
Note:
Docker version 19.03.7, build 7141c199a2
Have added necessary permission to docker command so that it doesn't
need sudo for running it
Running docker run with --user does not change the permission of the original existing files. From Docker reference:
The developer can set a default user to run the first process with the Dockerfile USER instruction. When starting a container, the operator can override the USER instruction by passing the -u option.
It only overrides the user running Node.js inside the container. During mount, the original permission and owner of /var/www/html is unchanged. Verify this by ls -n and see if the UID of the owner of the folder is the same when mounted inside Docker. Make sure the UID is the same as node user you specified.
I don't know how it works in your colleagues computers though. That's why it's important to use UID/GID instead just using username. The same username in the container can have different UID with the same username in the host.
EDIT: I checked that node image that you use contains node user with UID 1000. The first user created in Linux usually also has UID 1000. So if the /var/www/html is owned by UID 1000, it will run. But UID 1000 could possibly belong to different usernames in Docker and in the host. Because you specified --user node, which is translated into UID 1000 inside the container as username node itself exists, it won't work if /var/www/html is owned by different UID in your host, which probably is your case.
You have to add USER into Dockerfile before building
# App is running normal user mode
USER node
so now when you run docker image it will run with normal node user mode

Add a user to group docker and such a user can access unauthorized directories in container by mounting directories via -v

In my centos system, I add a user to group docker, and I found such a user can access any folder by attach folder to container via docker run -it -v path-to-directory:directory-in-container. For example, I have a folder with mode 700 which can only access by root, but if someone who doesn't have permission to access this folder run a container and mount this folder to container, he can access this folder in container.How can I prevent such a user to attach unauthorized directories to docker container? My docker version is 17.03.0-ce, system os centOS 7.0. Thanks!
You should refer and follow the container principles for security or external volume permission setting up. But you want to test simply for container features.
You can set up the path-to-directory access mode 777, yes it's world-readable-writable access mode. It's no additional owner-group setting and access mode setting for any container volume mapping.
chmod 777 /path/to/directory
Docker daemon runs as root and normally starts the containers as root, with users inside mapping one-to-one to the host users, so anybody in the docker group has effective root permissions.
There is an option to tell dockerd to run the containers via subusers of a specific user, see [https://docs.docker.com/engine/security/userns-remap/]. That prevents full root access, but everybody accessing the docker daemon will be running the containers under that user—and if that user is not them, they won't be able to usefully mount things in their home.
Also I believe it is incompatible with --privileged containers, but of course those give you full root access via other means as well anyway.

Making docker container write files that the host machine can delete

I have a docker-based build environment - in order to build my project, I run a docker container with the --volume parameter, so it can access my project directory and build it.
The problem is that the files created by the container cannot be deleted by the host machine. The only workaround I currently have is to start an interactive container with the directory mounted and delete it.
Bottom line question: It is possible to make docker write to the mounted area files with permissions such that the host can later delete them?
This has less to do with Docker and more to do with basic Unix file permissions. Your docker containers are running as root, which means any files created by the container are owned by root on your host. You fix this the way you fix any other file permission problem, by either (a) ensuring that that the files/directories are created with your user id or (b) ensuring that permissions allow you do delete the files even if they're not owned by you or (c) using elevated privileges (e.g., sudo rm ...) to delete the files.
Depending on what you're doing, option (a) may be easy. If you can run the contanier as a non-root user, e.g:
docker run -u $UID -v $HOME/output:/some/container/path ...
...then everything will Just Work, because the files will be created with your userid.
If the container must run as root initially, you may be able to take care of root actions in your ENTRYPOINT or CMD script, and then switch to another uid to run the main application. To do this, you would need to pass your user id into the container (e.g., as an environment variable), and then later use something like runuser to switch to the new userid:
exec runuser -u $TARGE_UID /some/command
If neither of the above is an option, then sudo rm -rf mydirectory should work just as well as spinning up an interactive container.
If you need your build artifacts just to put them to the docker image on the next stage then it is probably worth to use multi-stage build option.

docker mounted host directory file permissions

I am running the mqtt broker Mosqitto in a docker image.
I am using the following arguments
sudo docker run -d -p 1883:1883 -p 1884:1884 -v /home/mosquitto/apps/dev/mosquitto:/mosquitto --restart always -u mosquitto eclipse-mosquitto:1.4.
This should mount the host folder /home/mosquitto/apps/dev/mosquitto to the image folder /mosquitto
The problem is that the host user IDs (1001) and the docker user IDs (100) do not match.
If I do not specify -u mosquitto, the application complains about not being able to write to /mosquitto/logs/mosquitto.log
So I thought I'd specify -u mosquitto, to make the application inside the image run as user 1001, and therefore have write access to the mounted files.
Which worked.
But then, the Mosquitto application made a new database file on exit. That file was made with the 101 user as owner..
What exactly happens when I specify -U to docker.
How come it kind of did what I was expecting (allowed writing to host files) and kind of didn't do what I was expecting(still made files with the original image user id)
Maybe this is something to do with this specific docker image .. it runs some script internally that switches user?
How about making write access to log path for any user? It may be less secure. But if it is just logs, lets see application inside docker can write to it.
Or think about bootstrap some commands to the container to make permission changes inside.
If you are using Linux or OSX for your Docker location, most likely it is a security or file permissions issue. Go to this bug report Permission denied for directories created automatically by Dockerfile ADD command #1295 and jump to the end...there are several links to sub-bug reports where you can most likely find your solution. I had a very similar issue, and it turned out to be a selinux misconfiguration.

Resources