Docker with '--user' can not write to volume with different ownership - linux

I've played a lot with any rights combinations to make docker to work, but... at first my environment:
Ubuntu linux 15.04 and Docker version 1.5.0, build a8a31ef.
I have a directory '/test/dockervolume' and two users user1 and user2 in a group users
chown user1.users /test/dockervolume
chmod 775 /test/dockervolume
ls -la
drwxrwxr-x 2 user1 users 4096 Oct 11 11:57 dockervolume
Either user1 and user2 can write delete files in this directory.
I use standard docker ubuntu:15.04 image. user1 has id 1000 and user2 has id 1002.
I run docker with next command:
docker run -it --volume=/test/dcokervolume:/tmp/job_output --user=1000 --workdir=/tmp/job_output ubuntu:15.04
Within docker I just do simple 'touch test' and it works for user1 with id 1000. When I run docker with --user 1002 I can't write to that directory:
I have no name!#6c5e03f4b3a3:/tmp/job_output$ touch test2
touch: cannot touch 'test2': Permission denied
I have no name!#6c5e03f4b3a3:/tmp/job_output$
Just to be clear both users can write to that directory if not in docker.
So my question is this behavior by docker design or it is a bug or I missed something in the manual?

docker's --user parameter changes just id not a group id within a docker. So, within a docker I have:
id
uid=1002 gid=0(root) groups=0(root)
and it is not like in original system where I have groups=1000(users)
So, one workaround might be mapping passwd and group files into a docker.
-v /etc/docker/passwd:/etc/passwd:ro -v /etc/docker/group:/etc/group:ro
The other idea is to map a tmp directory owned by running --user and when docker's work is complete copy files to a final location
TMPFILE=`mktemp`; docker run -v $TMPFILE:/working_dir/ --user=$(id -u); cp $TMPDIR $NEWDIR
This discussion Understanding user file ownership in docker: how to avoid changing permissions of linked volumes brings some light to my question.

For both correct uid and gid mapping try: docker run --user=$(id -u):$(id -g)

Avoid use another use, because the UID is different and you can't sure about the user name. You can use root without problem inside container.

Related

Vulnerabilty when running docker as non-root?

I'm kind of fighting with privileges (no troll) for my Docker project as I'm trying to make one of my user on Docker, able to read/write a volume shared with the host, while the host user should also be able to read/write with the docker user in this directory.
In my case, nor Docker user, nor Host user should be root. This mean that, on the shared volume, the user which is running docker shouldn't be able to reach files in the volume that aren't. However, I discovered that running a volume as an user without root privileges do not save root's files
Example
For instance, in the following situation
Users directory with two files, one root one non-root, the user's name is user and has no root privileges, however he is part of Docker group :
C:/.../directory :
dwrx-rx--x root file1
dwrx-rx--x user file2
Users run docker through the command :
docker run -v /c/.../directory:/volume:rw -e USER_ID=$(id -u) -e GROUP_ID=$(id -g)
And the entrypoint of Docker is the following script.sh :
#!/bin/bash
usermod -u ${USER_ID} dockeruser \;
groupmod -g ${GROUP_ID} dockeruser ;
chown dockeruser:dockeruser -R /volume ;
exit;
The permissions, even are changed on the host's directory, even for roots file that I shouldn't have been to write on :
C:/.../directory :
dwrx-rx--x user file1
dwrx-rx--x user file2
Is it normal that, an user that isn't the root could do anything with files which do not belongs to him ?
I'm pretty a beginner so, I don't know if it's a misleading vulnerability due to the fact we force user to not be root nor sudo but in fact it doesn't change anything, or if I just am getting it wrong ^^, so feel free to tell me if it's not the way I should handle it.
Regards,
Waldo

docker.sock permission denied

When I try to run simple docker commands like:
$ docker ps -a
I get an error message:
Got permission denied ... /var/run/docker.sock: connect: permission denied
When I check permissions with
$ ls -al /var/run/
I see this line:
srw-rw---- root docker docker.sock
So, I follow an advice from many forums and add local user to docker group:
$ sudo usermod -aG docker $USER
But it does not help. I still get the very same error message. How can I fix it?
For those new to the shell, the command:
$ sudo usermod -aG docker $USER
needs to have $USER defined in your shell. This is often there by default, but you may need to set the value to your login id in some shells.
Changing the groups of a user does not change existing logins, terminals, and shells that a user has open. To avoid performing a login again, you can simply run:
$ newgrp docker
to get access to that group in your current shell.
Once you have done this, the user effectively has root access on the server, so only do this for users that are trusted with unrestricted sudo access.
Reason: The error message means that the current user can’t access the docker engine, because the user hasn't enough permissions to access the UNIX socket to communicate with the engine.
Quick Fix:
Run the command as root using sudo.
sudo docker ps
Change the permissions of /var/run/docker.sock for the current user.
sudo chown $USER /var/run/docker.sock
Caution: Running sudo chmod 777 /var/run/docker.sock will solve your problem but it will open the docker socket for everyone which is a security vulnerability as pointed out by #AaylaSecura. Hence it shouldn't be used, except for testing purposes on the local system.
Permanent Solution:
Add the current user to the docker group.
sudo usermod -a -G docker $USER
Note: You have to log out and log in again for the changes to take effect.
Refer to this blog to know more about managing Docker as a non-root user.
Make sure your $USER variable is set
$ echo $USER
$ sudo usermod -aG docker $USER
logout
Upon login, restart the docker service
$ sudo systemctl restart docker
$ docker ps
enter the command and explore docker without sudo command
sudo chmod 666 /var/run/docker.sock
As mentioned earlier in the comment the changes won't apply until your re-login. If you were doing a SSH and opening a new terminal, it would have worked in new terminal
But since you were using GUI and opening the new terminal the changes were not applied. That is the reason the error didn't go away
So below command did do its job, its just a re-login was missed
sudo usermod -aG docker $USER
You need to manage docker as a non-root user.
To create the docker group and add your user:
Create the docker group.
$ sudo groupadd docker
Add your user to the docker group.
$ sudo usermod -aG docker $USER
Log out and log back in so that your group membership is re-evaluated.
If testing on a virtual machine, it may be necessary to restart the virtual machine for changes to take effect.
On a desktop Linux environment such as X Windows, log out of your session completely and then log back in.
On Linux, you can also run the following command to activate the changes to groups:
$ newgrp docker
Verify that you can run docker commands without sudo.
$ docker run hello-world
As my user is and AD user, I have to add the AD user to the local group by manually editing /etc/group file. Unforrtunately the adduser commands do not seem to be nsswitch aware and do not recognize a user not locally defined when adding someone to a group.
Then reboot or refresh /etc/group. Now, you can use docker without sudo.
Regards.
***Important Note on these answers: the docker group is not always "docker" sometimes it is "dockerroot", for example the case of Centos 7 installation by
sudo yum install -y docker
The first thing you should do, after installing Docker, is
sudo tail /etc/group
it should say something like
......
sshd:x:74:
postdrop:x:90:
postfix:x:89:
yourusername:x:1000:yourusername
cgred:x:996:
dockerroot:x:995:
In this case, it is "dockerroot" not "docker". So,
sudo usermod -aG dockerroot yourusername
logout
When I try to run simple docker commands like: $ docker ps -a
I get an error message: Got permission denied ... /var/run/docker.sock: connect: permission denied.
[…] How can I fix it?
TL;DR: There are two ways (the first one, also mentioned in the question itself, was extensively addressed by other answers, but comes with security concerns; so I'll elaborate on this issue, and develop the second solution that can also be applicable for this fairly sensible use case).
Just to recall the context, the Docker daemon socket is owned by root:docker:
$ ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0 janv. 28 14:23 /var/run/docker.sock
so with this default setup, one needs to prepend all docker CLI commands by sudo.
To avoid this, one can either:
add one's user account ($USER) to the docker group − but that's quite risky to do this on one's personal workstation, as this would amount to provide all programs run by the user with root permissions without any sudo password prompt nor auditing.
See also:
this page in the official Docker documentation:
https://docs.docker.com/engine/security/#docker-daemon-attack-surface
this page that documents the related exploit:
https://fosterelli.co/privilege-escalation-via-docker.html
one can otherwise prepend sudo automatically without typing sudo docker manually: to this aim, a solution consists in adding the following alias in the ~/.bashrc (see e.g. this thread for details):
__docker() {
if [[ "${BASH_SOURCE[*]}" =~ "bash-completion" ]]; then
docker "$#"
else
sudo docker "$#"
fi
}
alias docker=__docker
Then one can test this by opening a new terminal and typing:
docker run --pul〈TAB〉 # → docker run --pull
# autocompletion works
docker run --pull always --rm -it debian:11 # ask one's password
\docker run --help # bypass the alias (thanks to the \) and ask no password
With the help of the below command I was able to execute the docker command without sudo
sudo setfacl -m user:$USER:rw /var/run/docker.sock
bash into container as root user
docker exec -it --user root <dc5> bash
create docker group if it's not already created
groupadd -g 999 docker
add user to docker group
usermod -aG docker jenkins
change permissions
chmod 777 /var/run/docker.sock
You have to use pns executer instead of docker.
run the following patch which modifies the configmap and you are all set.
kubectl -n argo patch cm workflow-controller-configmap -p '{"data": {"containerRuntimeExecutor": "pns"}}' ;
ref: https://www.youtube.com/watch?v=XySJb-WmL3Q&list=PLGHfqDpnXFXLHfeapfvtt9URtUF1geuBo&index=2&t=3996s

Docker mounting volume. Permission denied

I have a problem with creating new files in mounted docker volume.
Firstly after installation docker i added my user to docker group.
sudo usermod -aG docker $USER
Created as my $USER folder:
mkdir -p /srv/redis
And starting container:
docker run -d -v /srv/redis:/data --name myredis redis
when i want to create file in /srv/redis as a user which created container I have a problem with access.
mkdir /srv/redis/redisTest
mkdir: cannot create directory ‘/srv/redis/redisTest’: Permission denied
I tried to search in other threads but i didn't find appropriate solution.
The question title does not reflect the real problem in my opinion.
mkdir /srv/redis/redisTest
mkdir: cannot create directory ‘/srv/redis/redisTest’: Permission denied
This problem occurs very likely because when you run:
docker run -d -v /srv/redis:/data --name myredis redis
the directory /srv/redis ownership changes to root. You can check that by
ls -lah /srv/redis
This is normal consequence of mounting external directory to docker. To regain access you have to run
sudo chown -R $USER /srv/redis
I think /srv/redis/redisTest directory is created by user inside redis container, so it belong to redis container user.
Have you already check using ls -l to see that /srv/redis/redisTest directory belong to $USER?
This could also be related (as I just found out) to having SELinux activated. This answer on the DevOps Stack Exchange worked for me:
The solution is to simply append a :z to the [docker] run volume argument so that this:
docker run -v /host/foobar:/src_dir /bin/bash
becomes this:
docker run -it -v /host/foobar:/src_dir:z /bin/bash

Can't access mounted host directory in Docker container

I'm trying to get my Docker container to read and write to a host directory.
I run the container with:
docker run -it -v $(pwd):/file logstash-5.1.2
Inside the container, I can see that /file has the uid of my (non-root) user on the host, and the same permissions as that on the host:
drwxrwxrwx. 2 1156 1156 4096 Jul 21 05:00 file
and that root can't access /file.
root#c642b0c37e09:~# ls /file
ls: cannot open directory /file: Permission denied
I've read posts about creating a user in the container with the same uid as the host, but that seems to be frowned upon.
Why can't root access the directory? I thought it could do everything.
What's the best way to have the container read and write to the mounted directory, which is not owned by root, in Docker?
We're also using Rancher. Does that make it easier? I haven't yet come across something different there, mainly as I'm trying to see if I can do it purely within Docker.
You should change the context as svirt_sandbox_file_t to let container access this folder in this context.
If you are sure about folder permission then just only try;
chcon -R -t svirt_sandbox_file_t /your/host/path
If are not sure try;
chown -R groupId:userId /your/host/path
chcon -R -t svirt_sandbox_file_t /your/host/path
In here chcon command applies the SELinux context with changing the context of "/your/host/path" to the svirt_sandbox_file_t.

Running app inside Docker as non-root user

After yesterday's news of Shocker, it seems like apps inside a Docker container should not be run as root. I tried to update my Dockerfile to create an app user however changing permissions on app files (while still root) doesn't seem to work. I'm guessing this is because some LXC permission is not being granted to the root user maybe?
Here's my Dockerfile:
# Node.js app Docker file
FROM dockerfile/nodejs
MAINTAINER Thom Nichols "thom#thomnichols.org"
RUN useradd -ms /bin/bash node
ADD . /data
# This next line doesn't seem to have any effect:
RUN chown -R node /data
ENV HOME /home/node
USER node
RUN cd /data && npm install
EXPOSE 8888
WORKDIR /data
CMD ["npm", "start"]
Pretty straightforward, but when I ls -l everything is still owned by root:
[ node#ed7ae33e76e1:/data {docker-nonroot-user} ]$ ls -l /data
total 64K
-rw-r--r-- 1 root root 383 Jun 18 20:32 Dockerfile
-rw-r--r-- 1 root root 862 Jun 18 16:23 Gruntfile.js
-rw-r--r-- 1 root root 1.2K Jun 18 15:48 README.md
drwxr-xr-x 4 root root 4.0K May 30 14:24 assets/
-rw-r--r-- 1 root root 416 Jun 3 14:22 bower.json
-rw-r--r-- 1 root root 930 May 30 01:50 config.js
drwxr-xr-x 4 root root 4.0K Jun 18 16:08 lib/
drwxr-xr-x 42 root root 4.0K Jun 18 16:04 node_modules/
-rw-r--r-- 1 root root 2.0K Jun 18 16:04 package.json
-rw-r--r-- 1 root root 118 May 30 18:35 server.js
drwxr-xr-x 3 root root 4.0K May 30 02:17 static/
drwxr-xr-x 3 root root 4.0K Jun 18 20:13 test/
drwxr-xr-x 3 root root 4.0K Jun 3 17:38 views/
My updated dockerfile works great thanks to #creak's clarification of how volumes work. Once the initial files are chowned, npm install is run as the non-root user. And thanks to a postinstall hook, npm runs bower install && grunt assets which takes care of the remaining install steps and avoids any need to npm install -g any node cli tools like bower, grunt or coffeescript.
Check this post: http://www.yegor256.com/2014/08/29/docker-non-root.html In rultor.com we run all builds in their own Docker containers. And every time before running the scripts inside the container, we switch to a non-root user. This is how:
adduser --disabled-password --gecos '' r
adduser r sudo
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
su -m r -c /home/r/script.sh
r is the user we're using.
Update 2015-09-28
I have noticed this post getting a bit of attention. A word of advice for anyone who is potentially interested in doing something like this. I would try to use Python or another language as a wrapper for your script executions. Doing native bash scripts I had problems when trying to pass through a variety of arguments to my containers. Specifically there was issues with the interpretation/escaping of " and ' characters by the shell.
I was needing to change the user for a slightly different reason.
I created a docker image housing a full featured install of ImageMagick and Ffmpeg with a desire that I could do transformations on images/videos within my host OS. My problem was that these are command line tools, so it is slightly trickier to execute them via docker and then get the results back into the host OS. I managed to allow for this by mounting a docker volume. This seemed to work okay except that the image/video output was coming out as being owned by root (i.e. the user the docker container was running as), rather than the user whom executed the command.
I looked at the approach that #François Zaninotto mentioned in his answer (you can see the full make script here). It was really cool, but I preferred the option of creating a bash shell script that I would then register on my path. I took some of the concepts from the Makefile approach (specifically the user/group creation) and then I created the shell script.
Here is an example of my dockermagick shell script:
#!/bin/bash
### VARIABLES
DOCKER_IMAGE='acleancoder/imagemagick-full:latest'
CONTAINER_USERNAME='dummy'
CONTAINER_GROUPNAME='dummy'
HOMEDIR='/home/'$CONTAINER_USERNAME
GROUP_ID=$(id -g)
USER_ID=$(id -u)
### FUNCTIONS
create_user_cmd()
{
echo \
groupadd -f -g $GROUP_ID $CONTAINER_GROUPNAME '&&' \
useradd -u $USER_ID -g $CONTAINER_GROUPNAME $CONTAINER_USERNAME '&&' \
mkdir --parent $HOMEDIR '&&' \
chown -R $CONTAINER_USERNAME:$CONTAINER_GROUPNAME $HOMEDIR
}
execute_as_cmd()
{
echo \
sudo -u $CONTAINER_USERNAME HOME=$HOMEDIR
}
full_container_cmd()
{
echo "'$(create_user_cmd) && $(execute_as_cmd) $#'"
}
### MAIN
eval docker run \
--rm=true \
-a stdout \
-v $(pwd):$HOMEDIR \
-w $HOMEDIR \
$DOCKER_IMAGE \
/bin/bash -ci $(full_container_cmd $#)
This script is bound to the 'acleancoder/imagemagick-full' image, but that can be changed by editing the variable at the top of the script.
What it basically does is:
Create a user id and group within the container to match the user who executes the script from the host OS.
Mounts the current working directory of the host OS (using docker volumes) into home directory for the user we create within the executing docker container.
Sets the tmp directory as the working directory for the container.
Passes any arguments that are passed to the script, which will then be executed by the '/bin/bash' of the executing docker container.
Now I am able to run the ImageMagick/Ffmpeg commands against files on my host OS. For example, say I want to convert an image MyImage.jpeg into a PNG file, I could now do the following:
$ cd ~/MyImages
$ ls
MyImage.jpeg
$ dockermagick convert MyImage.jpeg Foo.png
$ ls
Foo.png MyImage.jpeg
I have also attached to the 'stdout' so I could run the ImageMagick identify command to get info on an image on my host, for e.g.:
$ dockermagick identify MyImage.jpeg
MyImage.jpeg JPEG 640x426 640x426+0+0 8-bit DirectClass 78.6KB 0.000u 0:00.000
There are obvious dangers about mounting the current directory and allowing any arbitrary command definition to be passed along for execution. But there are also many ways to make the script more safe/secure. I am executing this in my own non-production personal environment, so these are not of highest concern for me. But I would highly recommend you take the dangers into consideration should you choose to expand upon this script. It's also worth me mentioning that this script doesn't take an OS X host into consideration. The make file that I steal ideas/concepts from does take this into account, so you could extend this script to do so.
Another limitation to note is that I can only refer to files currently in the path for which I am executing the script. This is because of the way I am mounting the volumes, so the following would not work:
$ cd ~/MyImages
$ ls
MyImage.jpeg
$ dockermagick convert ~/DifferentDirectory/AnotherImage.jpeg Foo.png
$ ls
MyImage.jpeg
It's best just to go to the directory containing the image and execute against it directly. Of course I am sure there are ways to get around this limitation too, but for me and my current needs, this will do.
This one is a bit tricky, it is actually due to the image you start from.
If you look at the source, you notice that /data/ is a volume. So everything you do in the Dockerfile will be discarded and overridden at runtime by the volume that gets mounted then.
You can chown at runtime by changing your CMD to something like CMD chown -R node /data && npm start.
Note: I answer here because, given the generic title, this Question pops up in google when you look for a solution to "Running app inside Docker as non-root user". Hope it helps those who are stranded here.
With Alpine Linux you can create a system user like this:
RUN adduser -D -H -S -s /bin/false -u 1000 myuser
Everything in the Dockerfile after this line is executed with myuser.
myuser user has:
no password assigned
no home dir
no login shell
no root access.
This is from adduser --help:
-h DIR Home directory
-g GECOS GECOS field
-s SHELL Login shell
-G GRP Add user to existing group
-S Create a system user
-D Don't assign a password
-H Don't create home directory
-u UID User id
-k SKEL Skeleton directory (/etc/skel)
Note: This answer is given because many people looking for non-root usage will end up here. Beware, this does not address the issue that caused the problem, but is addressing the title and clarification to an answer given by #yegor256, which uses a non-root user inside the container. This answer explains how to accomplish this for non-debian/non-ubuntu use-case. This is not addressing the issue with volumes.
On Red Hat-based systems, such as Fedora and CentOS, this can be done in the following way:
RUN adduser user && \
echo "user ALL=(root) NOPASSWD:ALL" | tee -a /etc/sudoers.d/user && \
chmod 0440 /etc/sudoers.d/user
In your Dockerfile you can run commands as this user by doing:
RUN su - user -c "echo Hello $HOME"
And the command can be run as:
CMD ["su","-","user","-c","/bin/bash"]
An example of this can be found here:
https://github.com/gbraad/docker-dev/commit/644c51002f4b8e6fe5bb745638542a4c3d908b16

Resources