Using current user when running container in docker-compose - docker

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

Related

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

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).

docker volume masks parent folder in container?

I'm trying to use a Docker container to build a project that uses rust; I'm trying to build as my user. I have a Dockerfile that installs rust in $HOME/.cargo, and then I'm trying to docker run the container, map the sources from $HOME/<some/subdirs/to/project> on the host in the same subfolder in the container. The Dockerfile looks like this:
FROM ubuntu:16.04
ARG RUST_VERSION
RUN \
export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
# install library dependencies
apt-get install [... a bunch of stuff ...] && \
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUST_VERSION && \
echo 'source $HOME/.cargo/env' >> $HOME/.bashrc && \
echo apt-get DONE
The build container is run something like this:
docker run -i -t -d --net host --privileged -v /mnt:/mnt -v /dev:/dev --volume /home/stefan/<path/to/project>:/home/stefan/<path/to/project>:rw --workdir /home/stefan/<path/to/project> --name <container-name> -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro -v /etc/shadow:/etc/shadow:ro -u 1000 <image-name>
And then I try to exec into it and run the build script, but it can't find rust or $HOME/.cargo:
docker exec -it <container-name> bash
$ ls ~/.cargo
ls: cannot access '/home/stefan/.cargo': No such file or directory
It looks like the /home/stefan/<path/to/project> volume is masking the contents of /home/stefan in the container. Is this expected? Is there a workaround possible to be able to map the source code from a folder under $HOME on the host, but keep $HOME from the container?
I'm un Ubuntu 18.04, docker 19.03.12, on x86-64.
Dockerfile read variable in physical machine. So you user don't have in virtual machine.
Try change: $HOME to /root
echo 'source /root/.cargo/env' >> /root/.bashrc && \
I'll post this as an answer, since I seem to have figured it out.
When the Dockerfile is expanded, $HOME is /root, and the user is root. I couldn't find a way to reliably introduce my user in the build step / Dockerfile. I tried something like:
ARG BUILD_USER
ARG BUILD_GROUP
RUN mkdir /home/$BUILD_USER
ENV HOME=/home/$BUILD_USER
USER $BUILD_USER:$BUILD_GROUP
RUN \
echo "HOME is $HOME" && \
[...]
But didn't get very far, because inside the container, the user doesn't exist:
unable to find user stefan: no matching entries in passwd file
So what I ended up doing was to docker run as my user, and run the rust install from there - that is, from the script that does the actual build.
I also realized why writing to /home/$USER doesn't work - there is no /home/$USER in the container; mapping /etc/passwd and /etc/group in the container teaches it about the user, but does not create any directory. I could've mapped $HOME from the host, but then the container would control the rust versions on the host, and would not be that self contained. I also ended up needing to install rust in a non-standard location, since I don't have a writable $HOME in the container: I had to set CARGO_HOME and RUSTUP_HOME to do that.

run docker container as a arbitrary user passed to it while running the image

I want to run a docker container as an arbitrary user which is passed to the image while running it. For example docker run -u 1000 myimage.
The above is possible. However I want to create a home directory with this user 1000 while starting the container(possibly through CMD) and do my container service stuff within that directory.
Is this possible and some pointers would be useful on ways to achieve it.
First save your current user and group in variables:
export uid=$(id -u)
export gid=$(id -g)
Then to run your image,you have two options:
1) Run the image from the location of the app directory itself:
sudo docker run -d \
--user $uid:$gid \
-v $(pwd):/home/$USER \
--workdir="/home/$USER" \
myimage
2) Create a new directory for the app, e.g. at /home/$USER/app, but then you will have to write in command line your CMD from the docker file.
For example if this was your Dockerfile:
FROM node:7
WORKDIR /app
COPY package.json /app
COPY . /app
CMD node bin/www
Your would run it like that:
sudo docker run -d \
--user $uid:$gid \
-v $(pwd):/home/$USER \
--workdir="/home/$USER" \
hello-express \
bash -c "cp -rf /app/* /home/$USER/; node bin/www"
Here you pass the user to the container using $uid:$gid and you mount the user's home directory as a volume and then set it as the working directory.
I know it's quite complex, but it's the only way to achieve exactly what you want.
If you want a simpler solution, consider planning it differently. See this example for running a docker container as a non-root user.

Docker : execute commands as a non-root user

Earlier I used to run with the following command :
sudo docker run --pid=host -dit --restart unless-stopped --privileged -v /home/:/home/ --net=host ubuntu:latest bash -c "cd home && wget http://someurl.com/a.js -O /home/a.js && node a.js && tail -F anything"
This command would launch the container having a root user by default. So the wget http://someurl.com/a.js -O /home/a.js command used to work without any issues.
Now I want to get sound from the container. To make sure that the container and the host plays audio simultaneously I used pulseaudio socket otherwise I used to get device busy error as alsa captures the sound card.
Here is the new command I used to accomplish my requirement:
sudo docker run --pid=host -dit --restart unless-stopped --privileged --env PULSE_SERVER=unix:/tmp/pulseaudio.socket --env PULSE_COOKIE=/home/$USER/pulseaudio.cookie --volume /tmp/pulseaudio.socket:/tmp/pulseaudio.socket --volume /home/$USER/pulseaudio.client.conf:/etc/pulse/client.conf --user $(id -u):$(id -g) -v /home/:/home/ --net=host ubuntu:latest bash -c "cd home && wget http://someurl.com/a.js -O /home/a.js && node a.js && tail -F anything"
problem with pulseaudio is that it doesnt work when the user inside docker is a root user hence I have to use --user $(id -u):$(id -g) in the run command.
Now since the user is not root, the wget http://someurl.com/a.js -O /home/a.js command gives permission denied error.
I want this wget command to execute whenever I start my container.
I want to run the container as non-root as well as be able to execute the wget command also.
Is there any workaround for this?
1- Execute docker command with non-root user
If this is your case and don't want to run docker command with root user, follow this link .
create a docker group and add your current user to it.
$ sudo groupadd docker
$ sudo usermod -aG docker $USER
2- Execute commands inside docker! with non-root user
If I'm right you want to use a non-root user inside docker not the root!
The uid given to your user in the docker is related to the root docker images you are using, for example alphine or ubuntu:xenial as mentioned in this article
But you can simple change the user inside docker by changing a little bit as follow in your Dockerfile and add a new user and user it. like this:
RUN adduser -D myuser
USER myuser
ENTRYPOINT [“sleep”]
CMD [“1000”]
then in the docker file, if you gain the /bin/bash and execute id command in it, you will see that the id of user inside docker is changed.
Update:
If you have a ready to use Dockerfile, then create a new Dockerfile, for example it's name is myDocker, and put code below in it:
from myDockerfile
RUN adduser -D myuser
USER myuser
ENTRYPOINT [“sleep”]
CMD [“1000”]
then save this file,and build it:
$ docker build -t myNewDocker .
$ docker run myNewDocker <with your options>
I solved the issue by using a simple chmod 777 command.
First I executed docker run command without the -c flag or the wget command etc
sudo docker run --pid=host -dit --restart unless-stopped --privileged -v /home/:/home/ --net=host ubuntu:latest bash
Once the container was running I entered this container as a root user using this command :
sudo docker exec -it --user="root" bash
Now once inside the container I executed the command chmod 777 /home/a.js
Then I commited a new image with the above changes.
Run the new image with the wget command
sudo docker run --pid=host -dit --restart unless-stopped --privileged -v /home/:/home/ --net=host ubuntunew:latest bash -c "cd home && wget http://someurl.com/a.js -O /home/a.js && node a.js && tail -F anything"
Now the wget works perfectly in non-root mode
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.
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

How to create and run docker container with new user other than root?

I met a problem while using docker.
Now I have a ubuntu based docker container. And in the container ,the user id is root by default which is not my expectation, I suppose the user id is like abc which is another user account on the HOST OS running docker.
I have tried the following ways but all fail:
su abc;
Then running docker run xxx to bring up a container, but login the container, the user in container is still root.
Then by adding the -u flag for docker run: like :
docker run -t -i -u abc ubuntu /bin/bash
the the docker show errors unable to find user abc
Can some one tell me how to fix it?
Or does docker support run a container in which the user is a specific one than the default root?
You can create User inside Docker images. But for that you will have to extend base image. For example you can create user abc in Ubuntu as below,
FROM ubuntu:14.04
RUN apt-get update
# Replace 1000 with your user / group id
RUN export uid=1000 gid=1000 && \
mkdir -p /home/abc && \
echo "abc:x:${uid}:${gid}:Abc,,,:/home/abc:/bin/bash" >> /etc/passwd && \
echo "abc:x:${uid}:" >> /etc/group && \
echo "abc ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/abc && \
chmod 0440 /etc/sudoers.d/abc && \
chown ${uid}:${gid} -R /home/abc
USER abc
ENV HOME /home/abc
WORKDIR $HOME
CMD /bin/bash
Then you build and run it,
docker build -t abc .
docker run -it abc bash
you should see bash prompt with user abc like below,
abc#<container-hostname>:~$
According to https://medium.com/redbubble/running-a-docker-container-as-a-non-root-user-7d2e00f8ee15, this is possibly, but you can only refer to HOST users by their numerical ids. Read that helpful article for more details and a fuller explanation.

Resources