start a docker container in user mode with read-write access permission - docker

I try to start a new container from ubuntu 18.04 docker image. I do as follows:
pull the docker image
docer pull ubuntu:18.04
create a new container
docker run -ti -v $(pwd):/home/shared --name ubuntu_test ubuntu:18.04
and then log out.
start the created container
docker start ubuntu_test
log in as root user, update OS and install vim
docker exec -ti ubuntu_test /bin/bash and apt update, apt install -y vim
then log out.
log in as non-root user
docker exec -ti -u daemon ubuntu_test /bin/bash
Then I found that I have no permission to create new files or new folders.
I do not want to log in as root user since there could be some problems with mpirun.
Is there any solution for this problem ? Thank you for any help.

It is not like you (non-root user) don't have permissions to write or read. It is that everything on the system (files/folders) belong to the root user and no other user can modify anything by default.
You can create a new user as well as home folder for that user when you are building the image and then the user will be able to modify stuff in its home (standard linux stuff).
Example Dockerfile
FROM ubuntu
RUN groupadd --gid 1000 someuser \
&& useradd --uid 1000 --gid someuser --shell /bin/bash --create-home someuser
test with
docker build -t utest .
docker container run -it -u someuser utest /bin/bash
cd /home/someuser
touch myfile
If you need to add some other folders under that user's administration other than its home, you can use chown -R someuser:someuser <folder> which will recursively change ownership of the specified folder and everything in it to that of the new user.
Example: changing ownership of /etc folder
FROM ubuntu
RUN groupadd --gid 1000 someuser \
&& useradd --uid 1000 --gid someuser --shell /bin/bash --create-home someuser
RUN chown -R someuser:someuser /etc

Related

Make an existing Docker container rootless

I'm not asking how to create a rootless container from scratch. Rather, I've been given some software deployed as pre-built Docker container images that run as root by default. I need to modify these containers so they can be deployed on Kubernetes, which means I need to make these containers rootless. To be clear, I DO NOT have the source to these containers so I can't simply rebuild them from scratch.
I've found plenty of articles about building rootless containers in general, but they all assume you're building your containers from scratch. I've spent hours searching but can't find anything about modifying an existing container to be rootless.
I realize this might be a very open question, but I don't know all the things I need to take into consideration. Two things I've been able to gather is adding a line such as USER 1000 to Dockerfile, and adjusting ownership and permissions on certain files and folders. Beyond that, I'm not sure what I need to do.
Create users in the container and switch users;
Add a new user, named user;
Let this user have root privileges;
Set its password to password;
After the Container is started, log in as user and go directly to the user's home directory;
Put the following code snippet in the Dockerfile.
RUN useradd --create-home --no-log-init --shell /bin/bash user \
&& RUN adduser user sudo \
&& RUN echo 'user:password' | chpasswd
USER user
WORKDIR /home/user
Use fixuid to modify the uid and gid of non-root users in the container;
After creating a non-root user with the above code, the user's uid and gid are generally 1000:1000.
Docker and the host share a set of kernel, and there is still only one set of uid and gid controlled by the kernel. In other words, we execute the process as a newly created docker user (uid 1000) in the container, and the host will think that the process is executed by a user with a uid of 1000 on the host, and this user may not necessarily be our account, which is equivalent to us A user who has replaced someone else with an impostor makes it difficult to trace back to the real user.
To solve this problem, you can specify the uid as the user's uid when adding the user, such as 1002;
RUN addgroup --gid 1002 docker && \
adduser --uid 1002 --ingroup docker --home /home/docker --shell /bin/sh --gecos "" docker
A better solution is to use fixuid to switch the uid when the container starts:
RUN useradd --create-home --no-log-init --shell /bin/bash user\
&& adduser user sudo \
&& echo 'user:password' | chpasswd
RUN USER=user && \
GROUP=docker && \
curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.4.1/fixuid-0.4.1-linux-amd64.tar.gz | tar -C /usr/local/bin -xzf - && \
chown root:root /usr/local/bin/fixuid && \
chmod 4755 /usr/local/bin/fixuid && \
mkdir -p /etc/fixuid && \
printf "user: $USER\ngroup: $GROUP\n" > /etc/fixuid/config.yml
USER user:docker
ENTRYPOINT ["fixuid"]
At this time, you need to specify the uid and gid when starting the container. The command is as follows:
docker run --rm -it -u $(id -u):$(id -g) image-name bash

docker: bind mount host folder: how to manage dockerfiles for different host uid:gid

On my host my uid and gid are:
$ id ravi
uid=1000(ravi) gid=100(users)
i want to mount a folder host_test with uid:gid = 1000:100 into docker
I have the following docker and its id
$ docker run --rm -it python:3.7.9-buster /bin/bash
root#48d7d3122ffd:/# id root
uid=0(root) gid=0(root) groups=0(root)
root#48d7d3122ffd:/#
After going through various solutions, the best solution i see is to create a user and group same as host on docker image.
i.e
Dockerfile_mypc
FROM python:3.7.9-buster
RUN groupadd --gid 100 users \
&& useradd --uid 1000 --gid users --create-home ravi
WORKDIR /home/ravi
USER ravi
this now solves the problem of permissions
but when I want to use this Dockerfie on aws ubuntu instance, I see there the user ubuntu has 1000:1000 has uid and gid. So again i have to change the Dockerfile
Dockerfile_aws
FROM python:3.7.9-buster
RUN groupadd --gid 1000 users \
&& useradd --uid 1000 --gid users --create-home ubuntu
WORKDIR /home/ubuntu
USER ubuntu
I am just looking what is the best practise. Should i make Dockerfiles for each system where ever i am going to setup like
Dockerfile_mypc
Dockerfile_aws
or is there any way i can do this with single dockerfile
Because i have to mount the host folder from my pc to docker in development and also mount host folder from aws ubuntu instance to docker in production

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

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