Starting docker container inside a docker with non-root permission [duplicate] - docker

I have this Dockerfile:
FROM chekote/gulp:latest
USER root
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y sudo libltdl-dev
ARG dockerUser='my-user-name';
ARG group='docker';
# crate group if not exists
RUN if ! grep -q -E "^$group:" /etc/group; then groupadd $group; fi
# create user if not exists
RUN if ! grep -q -E "^$dockerUser:" /etc/passwd; then useradd -c 'Docker image creator' -m -s '/bin/bash' -g $group $dockerUser; fi
# add user to the group (if it was present and not created at the line above)
RUN usermod -a -G ${group} ${dockerUser}
# set default user that runs the container
USER ${dockerUser}
That I build this way:
docker build --tag my-gulp:latest .
and finally run by script this way:
#!/bin/bash
image="my-gulp:latest";
workDir='/home/gulp/project';
docker run -it --rm \
-v $(pwd):${workDir} \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
${image} /bin/bash
that logs me into the docker container properly but when I want to see images
docker images
or try to pull image
docker pull hello-world:latest
I get this error:
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.38/images/json: dial unix /var/run/docker.sock: connect: permission denied
How to create docker image from chekote/gulp:latest so I can use docker inside it without the error?
Or maybe the error is because of wrong docker run command?

A quick way to avoid that. Add your user to the group.
sudo gpasswd -a $USER docker
Then set the proper permissions.
sudo setfacl -m "user:$USER:rw" /var/run/docker.sock
Should be good from there.

The permission matching happens only on numeric user ID and group ID. If the socket file is mode 0660 and owned by user ID 0 and group ID 32, and you're calling it as a user with user ID 1000 and group IDs 1000 and 16, it doesn't matter if one /etc/group file names gid 32 as docker and the other one names gid 16 the same; the numeric gids are different and you can't access the file. Also, since the actual numeric gid of the Docker group will vary across systems, this isn't something you can bake into the Dockerfile.
Many Docker images just run as root; if they do, they can access a bind-mounted Docker socket file regardless of its permissions.
If you run as a non-root user, you can use the docker run --group-add option to add a (numeric) gid to the effective user; it doesn't specifically need to be mentioned in the /etc/groups file. On a Linux host you might run:
docker run --group-add $(stat -c '%g' /var/run/docker.sock) ...
You wouldn't usually install sudo in a Dockerfile (it doesn't work well for non-interactive programs, you usually don't do a whole lot in interactive shells because of the ephemeral nature of containers, and you can always docker exec -u 0 to get a root shell) though installing some non-root user is often considered a best practice. You could reduce the Dockerfile to
FROM node:8
RUN apt-get update
# Trying to use the host's `docker` binary may not work well
RUN apt-get install -y docker.io
# Install the single node tool you need
RUN npm install -g gulp
# Get your non-root user
RUN adduser myusername
# Normal Dockerfile bits
WORKDIR ...
COPY ...
RUN gulp
USER myusername
CMD ["npm", "run", "start"]
(That Docker base image has a couple of things that don't really match Docker best practices, and doesn't seem to be updated routinely; I'd just use the standard node image as a base and add the one build tool you need on top of it.)

open terminal and type this command
sudo chmod 666 /var/run/docker.sock
let me know the results...

You need the --privileged flag with your docker run command.
By the way , you can just use the docker in docker , image from docker for this kind of use case.
https://asciinema.org/a/24707
https://hub.docker.com/_/docker/

The error has nothing to do with docker pull or docker image subcommand, but rather that you need to call the docker command as either a user with write access to the docker socket (for example, by being root, using sudo, or by being in the docker group).

Related

Using current user when running container in docker-compose

Is there a way to execute or login as current user to a bash of specific container . I tried running docker-compose exec -u $USER phoenix bash but it says unable to find user raz: no matching entries in passwd file
I tried another way by adding a useradd command in a dockerfile.
FROM elixir:latest
ARG USER_ID
ARG GROUP_ID
RUN addgroup --gid $GROUP_ID raz
RUN adduser --disabled-password --gecos '' --uid $USER_ID --gid $GROUP_ID raz
USER raz
RUN apt-get update && \
apt-get install -y postgresql-client && \
apt-get install -y inotify-tools && \
apt-get install -y nodejs && \
curl -L https://npmjs.org/install.sh | sh && \
mix local.hex --force && \
mix archive.install hex phx_new 1.5.3 --force && \
mix local.rebar --force
COPY . /app
WORKDIR /app
COPY ./entrypoint.sh /entrypoint.sh
RUN ["chmod", "+x", "/entrypoint.sh"]
ENTRYPOINT ["/entrypoint.sh"]
but when I run docker-compose build I get a permission denied error when running the apt-get commands.
I also look for gosu as a step down root user but it seems complicated.
Is it possible for added user in Dockerfile command to have same permission as my current user?
I'm running WSL2 btw.
This question is pretty interesting. Let me begin with a short explanation:
Understanding the problem
In fact the user that exists inside container will be valid only inside the container itself. What you're trying to do is to use a user that exists outside a container, i.e. your docker host, inside a container. Unfortunately this movement can't be done in a normal way.
For instance, let me try to change to my user in order to get this container:
$ docker run -it --rm --user jon ubuntu whoami
docker: Error response from daemon: unable to find user jon: no matching entries in passwd file.
I tried to run a classic ubuntu container inside my docker host; Although the user exists on my local machine, the Docker image says that didn't find the user.
$ id -a
uid=1000(jon) gid=1001(jon) groups=1001(jon),3(sys),90(network),98(power),108(vboxusers),962(docker),991(lp),998(wheel),1000(autologin)
The command above was executed on my computer, proving that "jon" username exists.
Making my username available inside a container: a docker trick
I suppose that you didn't create a user inside your container. For demonstration I'm going to use the ubuntu docker image.
The trick is to mount both files responsible for handling your user and group definition inside the container, enabling the container to see you inside of it.
$ docker run -it --rm --volume /etc/passwd:/etc/passwd:ro --volume /etc/group:/etc/group:ro --user $(id -u) ubuntu whoami
jon
For a more complete example:
$ docker run -it --rm --volume /etc/passwd:/etc/passwd:ro --volume /etc/group:/etc/group:ro --user $(id -u):$(id -g) ubuntu "id"
uid=1000(jon) gid=1001(jon) groups=1001(jon)
Notice that I used two volumes pointing to two files? /etc/password and /etc/group?
Both I mounted read only (appending ":ro") just for safety.
Also notice that I used the id -u, which brings me the user id (1000 on my case), forcing the user id for being the same of mine defined on my /etc/password file.
Caveat
If you try to set the username to jon rather than the UID, you're going to run into an issue:
$ docker run -it --rm --volume /etc/passwd:/etc/passwd:ro --volume /etc/group:/etc/group:ro --user jon ubuntu whoami
docker: Error response from daemon: unable to find user jon: no matching entries in passwd file.
This happens because the docker engine would try to change the username before mouting the volumes and this should exists before running the container. If you provide a numeric representation of the user, this one doesn't needs to exist within the container, causing the trick to work;
https://docs.docker.com/engine/reference/run/#user
I hope being helpful. Be safe!
Building on top of the answer by Joepreludian, focusing on docker-compose:
You can use the user: and volumes: options in the compose file. For example:
my-service:
image: ubuntu:latest
user: ${MY_UID}:${MY_GID}
volumes:
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro
and define these variables where you are starting your compose:
MY_UID="$(id -u)" MY_GID="$(id -g)" docker-compose up

Revert CHMOD 666 cmd for Docker

I've installed Docker on an Ubuntu Server 18.04.
I received permissions error when trying to run docker commands, so I run this command:
sudo chmod 666 /var/run/docker.sock
Now I found that the tidy solution is to follow next steeps:
Create the docker group.
sudo groupadd docker
Add your user to the docker group.
sudo usermod -aG docker ${USER}
You would need to loog out and log back in so that your group membership is re-evaluated or type the following command:
su -s ${USER}
As I'm new with Linux management, I'm not sure on how to revert the last chmod command.
Is there a way to do it?
The default permissions on /var/run/docker.sock is generally owned by user root and group docker, with mode 0660 (read/write permissions for owner and group, no permissions for others).
sudo chmod 0660 /var/run/docker.sock
Remember that anyone who can run any docker command at all can trivially root the host
docker run --rm -it -v /:/host busybox vi /host/etc/sudoers
For a development system adding your normal user to the docker group might be acceptable; if you have actual production-oriented data on the system, requiring sudo might be more appropriate.

How to operate the k8s cluster in the docker container

How does a docker container running on a docker machine instead of a k8s pod operate the k8s cluster. For example, if i need to do something like this inside a container:
kubectl get pods
In my dockerfile, I installed kubectl
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
RUN chmod +x ./kubectl
RUN sudo mv ./kubectl /usr/local/bin/kubectl
when i run kubectl get pods, the result is as follows:
kubectl get pod
error: no configuration has been provided, try setting KUBERNETES_MASTER environment variable
So I mounted the config into the docker container at docker runcommand
docker run -v /root/.kube/config:/root/.kube/config my-images
the result is as follows:
kubectl get pod
Error in configuration:
* unable to read client-cert /root/.minikube/profiles/minikube/client.crt for minikube due to open /root/.minikube/profiles/minikube/client.crt: no such file or directory
* unable to read client-key /root/.minikube/profiles/minikube/client.key for minikube due to open /root/.minikube/profiles/minikube/client.key: no such file or directory
* unable to read certificate-authority /root/.minikube/ca.crt for minikube due to open /root/.minikube/ca.crt: no such file or directory
This seems to be due to the current-context: minikube in the k8s config file
Then mount the authentication file again, it run success.
Now, I can call the kubectl get pods command or otherwise manipulate a cluster outside the container when I mount -v /root/.kube/config:/root/.kube/config -v /root/.minikube/:/root/.minikube/, however, this does not apply to cluster mounts created by kubeadm or otherwise.
But I want to be able to mount the required configuration files and so on to the container in a uniform way so that I can use the same command to manipulate the k8s cluster, which may be created by minikube or rancher k3s or kubeadm
In summary, I want to mount a uniform set of files or directories for all cases of the k8s cluster, such as -v file: file -v dir:dir, to implement operations on the k8s cluster created in any way, such as getting the pod status, creating, deleting various types of resources, and so on
I need to have the maximum permission to operate on k8s
Can someone please tell me what is it that I need to do?
I think you can set the Docker user when running your container
You can run (in this example - ubuntu image) with an explicit user id and group id.
$ docker run -it --rm \
--mount "type=bind,src=$(pwd)/shared,dst=/opt/shared" \
--workdir /opt/shared \
--user "$(id -u):$(id -g)" \
ubuntu bash
The difference is ‘–user “$(id -u):$(id -g)“’ - they tell the container to run with the current user id and group id which are obtained dynamically through bash command substitution by running the “id -u” and “id -g” and passing on their values.
This can be good enough already. The problem here is, that the user and group don’t really exist in the container. This approach works for the terminal command, but the session looks broken and you’ll see some ugly error messages like:
"groups: cannot find name for group ID"
"I have no name!"
- your container, complaining
While bash works, some apps might refuse to run if those configs look fishy.
Next you have to configure and run your Docker containers correctly, so you don’t have to fight permission errors and access your files easily.
As you should create a non-root user in your Dockerfile in any case, this is a nice thing to do. You might as well set the user id and group id explicitly.
Below is a minimal Dockerfile which expects to receive build-time arguments, and creates a new user called “user”:
FROM ubuntu
ARG USER_ID
ARG GROUP_ID
RUN addgroup --gid $GROUP_ID user
RUN adduser --disabled-password --gecos '' --uid $USER_ID --gid $GROUP_ID user
USER user
Take a look: add-user-to-container.
You can use this Dockerfile, to build a fresh image with the host uid and gid. This image, needs to be built specifically for each machine it will run on to make sure everything is in order.
Then, you can run use this image for our command. The user id and group id are correct without having to specify them when running the container.
$ docker build -t your-image \
--build-arg USER_ID=$(id -u) \
--build-arg GROUP_ID=$(id -g) .
$ docker run -it --rm \
--mount "type=bind,src=$(pwd)/shared,dst=/opt/shared" \
--workdir /opt/shared \
your-image bash
There is no need to use “chown”, and you will get rid of annoying permission errors anymore.
Please take a look on this very interesting article: kubernetes-management-docker, docker-shared-permissions.

how to correctly use system user in docker container

I'm starting containers from my docker image like this:
$ docker run -it --rm --user=999:998 my-image:latest bash
where the uid and gid are for a system user called sdp:
$ id sdp uid=999(sdp) gid=998(sdp) groups=998(sdp),999(docker)
but: container says "no"...
groups: cannot find name for group ID 998
I have no name!#75490c598f4c:/home/myfolder$ whoami
whoami: cannot find name for user ID 999
what am I doing wrong?
Note that I need to run containers based on this image on multiple systems and cannot guarantee that the uid:gid of the user will be the same across systems which is why I need to specify it on the command line rather than in the Dockerfile.
Thanks in advance.
This sort of error will happen when the uid/gid does not exist in the /etc/passwd or /etc/group file inside the container. There are various ways to work around that. One is to directly map these files from your host into the container with something like:
$ docker run -it --rm --user=999:998 \
-v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro \
my-image:latest bash
I'm not a fan of that solution since files inside the container filesystem may now have the wrong ownership, leading to potential security holes and errors.
Typically, the reason people want to change the uid/gid inside the container is because they are mounting files from the host into the container as a host volume and want permissions to be seamless across the two. In that case, my solution is to start the container as root and use an entrypoint that calls a script like:
if [ -n "$opt_u" ]; then
OLD_UID=$(getent passwd "${opt_u}" | cut -f3 -d:)
NEW_UID=$(stat -c "%u" "$1")
if [ "$OLD_UID" != "$NEW_UID" ]; then
echo "Changing UID of $opt_u from $OLD_UID to $NEW_UID"
usermod -u "$NEW_UID" -o "$opt_u"
if [ -n "$opt_r" ]; then
find / -xdev -user "$OLD_UID" -exec chown -h "$opt_u" {} \;
fi
fi
fi
The above is from a fix-perms script that I include in my base image. What's happening there is the uid of the user inside the container is compared to the uid of the file or directory that is mounted into the container (as a volume). When those id's do not match, the user inside the container is modified to have the same uid as the volume, and any files inside the container with the old uid are updated. The last step of my entrypoint is to call something like:
exec gosu app_user "$#"
Which is a bit like an su command to run the "CMD" value as the app_user, but with some exec logic that replaces pid 1 with the "CMD" process to better handle signals. I then run it with a command like:
$ docker run -it --rm --user=0:0 -v /host/vol:/container/vol \
-e RUN_AS app_user --entrypoint /entrypoint.sh \
my-image:latest bash
Have a look at the base image repo I've linked to, including the example with nginx that shows how these pieces fit together, and avoids the need to run containers in production as root (assuming production has known uid/gid's that can be baked into the image, or that you do not mount host volumes in production).
It's strange to me that there's no built-in command-line option to simply run a container with the "same" user as the host so that file permissions don't get messed up in the mounted directories. As mentioned by OP, the -u $(id -u):$(id -g) approach gives a "cannot find name for group ID" error.
I'm a docker newb, but here's the approach I've been using in case it helps others:
# See edit below before using this.
docker run --rm -it -v /foo:/bar ubuntu:20.04 sh -c "useradd -m -s /bin/bash $USER && usermod -a -G sudo $USER && su - $USER"
I.e. add a user (useradd) with a matching name, make it sudo (usermod), then open a terminal with that user (su -).
Edit: I've just found that this causes a E: List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied) error when trying to use apt. Using sudo gives the error -su: sudo: command not found because sudo isn't install by default on the image I'm using. So the command becomes even more hacky and requires running an apt update and apt install sudo at launch:
docker run --rm -it -v /foo:/bar ubuntu:20.04 sh -c "useradd -m -s /bin/bash $USER && usermod -a -G sudo $USER && apt update && apt install sudo && passwd -d $USER && su - $USER"
Not ideal! I'd have hoped there was a much more simple way of doing this (using command-line options, not creating a new image), but I haven't found one.
1) Make sure that the user 999 has right privilege on the current directory, you need to try something like this in your docker file
FROM
RUN mkdir /home/999-user-dir && \
chown -R 999:998 /home/999-user-dir
WORKDIR /home/999-user-dir
USER 999
try to spin up the container using this image without the user argument and see if that works.
2) other reason could be permission issue on the below files, make sure your group 998 has read permission on these files
-rw-r--r-- 1 root root 690 Jan 2 06:27 /etc/passwd
-rw-r--r-- 1 root root 372 Jan 2 06:27 /etc/group
Thanks
So, on your host you probably see your user and group:
$ cat /etc/passwd
sdp:x:999:998::...
But inside the container, you will not see them in /etc/passwd.
This is the expected behavior, the host and the container are completely separated as long as you don't mount the /etc/passwd file inside the container (and you shouldn't do it from security perspective).
Now if you specified a default user inside your Dockerfile, the --user operator overrides the USER instruction, so you left without a username inside your container, but please notice that specifying the uid:gid option means that the container have the permissions of the user with the same uid value in the host.
Now for your request not to specify a user in the Dockerfile - that shouldn't be a problem. You can set it on runtime like you did as long as that uid matches an existing user uid on the host.
If you have to run some of the containers in privileged mode - please consider using user namespace.

How to run docker image as a non-root user?

I'm new to docker. When I run a docker images like ubuntu image by using the command,
sudo docker run -i -t ubuntu:14.04
By default, it is entering into the container as root like this.
I searched regarding this, but I couldn't get any of how to start a docker image as a non root user as I'm completely a starter for this topic.
It would be great if someone explains with an example of how to run a docker image as a non root user.
the docker run command has the -u parameter to allow you to specify a different user. In your case, and assuming you have a user named foo in your docker image, you could run:
sudo docker run -i -t -u foo ubuntu:14.04 /bin/bash
NOTE: The -u parameter is the equivalent of the USER instruction for Dockerfile.
This is admittedly hacky, but good for those quick little containers you start just to test something quickly:
#!/bin/bash
set -eu
NAME=$1
IMG=$2
#UID=$(id -u)
USER=$(id -un)
GID=$(id -g)
GROUP=$(id -gn)
docker run -d -v /tmp:/tmp -v "/home/$USER:/home/$USER" -h "$NAME" --name "$NAME" "$IMG" /bin/bash
docker exec "$NAME" /bin/bash -c "groupadd -g $GID $GROUP && useradd -M -s /bin/bash -g $GID -u $UID $USER"
Full version of the script I use here:
https://github.com/ericcurtin/staging/blob/master/d-run
udocker is a basic variant of docker which runs in user space:
udocker is a basic user tool to execute simple docker containers in user space without requiring root privileges. Enables download and execution of docker containers by non-privileged users in Linux systems where docker is not available. It can be used to pull and execute docker containers in Linux batch systems and interactive clusters that are managed by other entities such as grid infrastructures or externally managed batch or interactive systems.
It is not advisable to allow running docker without sudo as Docker has no auditing or logging built in, while sudo does.
If you want to give docker access to non-root users Red Hat recommends setting up sudo.
Add an entry like the following to /etc/sudoers.
dwalsh ALL=(ALL) NOPASSWD: /usr/bin/docker
Now, set up an alias in ~/.bashrc for running the docker command:
alias docker="sudo /usr/bin/docker"
Now when the user executes the docker command as non-root it will be allowed and get proper logging.
docker run -ti --privileged -v /:/host fedora chroot /host
Look at the journal or /var/log/messages.
journalctl -b | grep docker.*privileged
Aug 04 09:02:56 dhcp-10-19-62-196.boston.devel.redhat.com sudo[23422]: dwalsh : TTY=pts/3 ; PWD=/home/dwalsh/docker/src/github.com/docker/docker ; USER=root ; COMMAND=/usr/bin/docker run -ti --privileged -v /:/host fedora chroot /host

Resources