Dockerfile overriding env var at "docker run" time - docker

Dockerfile
FROM ubuntu
ENV UID "1234"
ENV USERNAME "default"
RUN addgroup $USERNAME && useradd -u $UID -g $USERNAME -ms /bin/bash $USERNAME
CMD ["/usr/bin/id", "-u", "myname"]
and running docker via:
docker build -t setuser .
docker run -e UID=5555 -e USERNAME=myname setuser
OUTPUT
/usr/bin/id: 'myname': no such user
this error tells me that useradd in Dockerfile was not executed during "docker run" time.
how could I achieve this?
CMD ["/usr/bin/id", "-u", "default"] works but i want to be able to supply the UID and USERNAME at run time, not at Dockerfile build time

To elaborate Henry's answer
Following portion of your Dockerfile executed when you build your image.
FROM ubuntu
ENV UID "1234"
ENV USERNAME "default"
RUN addgroup $USERNAME && useradd -u $UID -g $USERNAME -ms /bin/bash $USERNAME
So, this time, UID=1234 & USERNAME=default are set.
When you run your image, It starts with ENTRYPOINT & CMD. It has no effect on RUN addgroup $USERNAME ...
So you need to run a script to use your passing ENV.
#!/bin/bash
addgroup $USERNAME && useradd -u $UID -g $USERNAME -ms /bin/bash $USERNAME
id -u $USERNAME
Here, your passing ENV values will be used.

The useradd was executed when the image was created. If you want to run some commands when the container is started put them into a script that is executed at start time.

Related

Dockerfile change usergroup without logout/login

In Docker file I have this
FROM ubuntu
RUN apt update && apt -y upgrade
RUN apt install -y sudo
# Setup ops user use defaults uid 1000 gid 1000
RUN useradd -d /home/myuser -aG sudo \
&& usermod -aG sudo root \
&& echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers
when execute
docker run -dit -u 1000:1000 myimage "/bin/bash"
docker exec -it 23u898908 "/bin/bash"
I get
myuser#23u898908$ id
uid=1000(myuser) gid=1000(myuser) groups=1000(myuser)
myuser#23u898908$ id myuser
uid=1000(myuser) gid=1000(myuser) groups=1000(myuser),27(sudo)
myuser#23u898908$ sudo ls
file.txt
in other words, the groups are working, but not showing in the id command, but show in the id myuser command, just curious if there is something I am missing, or is it by design?
if executed
myuser#23u898908$sudo su -l myuser
$id
uid=1000(myuser) gid=1000(myuser) groups=1000(myuser),27(sudo)
expected behaviour is to show all groups with just the id command, is this a bug maybe??
you must relogin or restart container to refresh it. id takes it for current session
Solved.
Basically there is a need to terminate the bash session and re-establish it again by adjusting the above commands in Dockerfile by adding exit at the end of last shell command, that will enforce a new bash session to be kicked off.
RUN useradd -d /home/myuser -aG sudo \
&& usermod -aG sudo root \
&& echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers && exit
USER myuser
WORKDIR /home/myuser
Now when I do docker run -dit myimage "/bin/bash"
I get the $ prompt and $id produces the expected results.
The catch is, there is no need to use --user 1000:1000 on the docker run command.

how to make non root user as sudo user in docker alpine image?

I am trying build cassandra docker image using alpine based os. on the container run process i am getting permission related issue, as i am running as cassandra user. i am unable to run sudo and switch my user cassandra as sudo user. below is my sample docker file, shows only sudo user related logic--
FROM alpine:latest
RUN apk --no-cache update \
&& apk --no-cache add sudo
copy run.sh /usr/local/
RUN addgroup -S cassandra && adduser -S cassandra -G cassandra
RUN chown -R cassandra:cassandra /home/cassandra/
RUN echo 'cassandra ALL=(ALL) /bin/su' >> /etc/sudoers
USER cassandra
ENTRYPOINT [ "sh","/usr/local/run.sh"]
after login to container i am unable to perform any sudo related task.
First thing, you do not need to assign root permission to newly created user, which kill purpose of the user.
So you do not need to change user to root user, you can run command in the running container with root user.
docker exec -it --user root mycontainer sh
or in Dockerfile
USER root
# Run root operation here
# Change user back to cassandra
USER cassandra
Btw you can create root user using below commands
Dockerfile
RUN adduser -D $USER && mkdir -p /etc/sudoers.d \
&& echo "$USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USER \
&& chmod 0440 /etc/sudoers.d/$USER
USER $USER
WORKDIR $HOME
RUN whoami
RUN sudo whoami
Build Output
Step 9/11 : RUN whoami
---> Running in d52065213d2d
default
Removing intermediate container d52065213d2d
---> c1b526ea8342
Step 10/11 : RUN sudo whoami
---> Running in 5f4ddd11a5f2
root

Dockerfile, groupadd with GUI parameter

I am trying to add group with id declared in dockerfile, however I always get error:
groups: cannot find name for group ID 1001
My dockerfile:
FROM python:3.7.1
ARG UID=1001
RUN apt-get update && apt-get install -y openssh-server sudo
RUN mkdir /var/run/sshd
RUN echo 'root:pycharm' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed 's#session\s*required\s*pam_loginuid.so#session optional pam_loginuid.so#g' -i /etc/pam.d/sshd
RUN groupadd -r charm -g 1001
RUN useradd -ms /bin/bash charm -g charm -u 1001
RUN echo "export VISIBLE=now" >> /etc/profile
ADD helpers /opt/.pycharm_helpers
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
Error message I get when I try to enter container with:
docker exec -ti -u 1001 pydebug1 bash
Group doesn't exists in /etc/group file. When I run commands inside container then works but I want to have them inside Dockerfile.
Saved your dockerfile content in Dockerfile and touched a file with name helpers.
Then build the image and enter into the image. Screen shot shows 2nd build, commit hash etc and id from the image. You can see all the commands in screen shot.
You may build as docker build -t pydebug1 . as well.

Dockerfile replicate the host user UID and GID to the image

Similar to the SO post about replicating UID/GID in container from host but how do you build the image with a user with replicate UID and GID? Preferably, how do you do it with a dockerfile?
I can do it with a bash script:
#!/bin/bash
# current uid and gid
curr_uid=`id -u`
curr_gid=`id -g`
# create bb.dockerfile:
cat << EOF1 > bb.dockerfile
FROM ubuntu:xenial-20170214
ARG UNAME=testuser
EOF1
echo ARG UID=${curr_uid} >> bb.dockerfile
echo ARG GID=${curr_gid} >> bb.dockerfile
cat << EOF2 >> bb.dockerfile
RUN groupadd -g \$GID \$UNAME
RUN useradd -m -u \$UID -g \$GID -s /bin/bash \$UNAME
USER \$UNAME
CMD /bin/bash
EOF2
docker build -f bb.dockerfile -t testimg .
This bash will generate a docker file as the following and build on it.
FROM ubuntu:xenial-20170214
ARG UNAME=testuser
ARG UID=1982
ARG GID=1982
RUN groupadd -g $GID $UNAME
RUN useradd -m -u $UID -g $GID -s /bin/bash $UNAME
USER $UNAME
CMD /bin/bash
What I'm asking for, is to remove the hardcoded host UID 1982 and GID 1982 from the dockerfile.
You can pass it as a build arg. Your Dockerfile can be static:
FROM ubuntu:xenial-20170214
ARG UNAME=testuser
ARG UID=1000
ARG GID=1000
RUN groupadd -g $GID -o $UNAME
RUN useradd -m -u $UID -g $GID -o -s /bin/bash $UNAME
USER $UNAME
CMD /bin/bash
Then you'd pass the options on your build command:
docker build --build-arg UID=$(id -u) --build-arg GID=$(id -g) \
-f bb.dockerfile -t testimg .
Note that I've solved similar problems to this a different way, by running an entrypoint as root that looks a file/directory permissions of the host volume mount, and adjust the uid/gid of the users inside the container to match the volume uid/gid. After making that change, it drops access from the root user to the modified uid/gid user and runs the original command/entrypoint. The result is the image can be run unchanged on any developer machine. An example of this can be found in my jenkins-docker repo:
https://github.com/sudo-bmitch/jenkins-docker
Eventually the bb.bash looks like:
#!/bin/bash
# current uid and gid
curr_uid=`id -u`
curr_gid=`id -g`
# create bb.dockerfile:
cat << EOF2 > bb.dockerfile
FROM ubuntu:xenial-20180417
ARG UNAME=testuser
ARG UID=1000
ARG GID=1000
RUN groupadd -g \$GID \$UNAME
RUN useradd -m -u \$UID -g \$GID -s /bin/bash \$UNAME
USER \$UNAME
CMD /bin/bash
EOF2
docker build --build-arg UID=${curr_uid} --build-arg GID=${curr_gid} \
-f bb.dockerfile -t testimg .
Then another script is to create the container:
#!/bin/bash
docker run -it -d -v $(pwd)/shared:/home/testuser/shared \
--name testcontainer -P testimg

How to add user with dockerfile?

How can I add a user with Dockerfile - the following does not work.
USER vault
WORKDIR /usr/local/bin/vault
My full Dockerfile:
FROM alpine:3.4
RUN apk update && apk add curl unzip
RUN useradd -ms /bin/bash vault
USER vault
WORKDIR /usr/local/bin/vault
ADD /vault.hcl /etc/vault/vault.hcl
RUN curl -SL https://releases.hashicorp.com/vault/0.5.0/vault_0.5.0_linux_amd64.zip > vault.zip
RUN unzip vault.zip -d /usr/local/bin && rm vault.zip
Use useradd instead of its interactive adduser to add user.
RUN useradd -ms /bin/bash vault
Below command will not create user .
USER vault
WORKDIR /usr/local/bin/vault
it will use vault user
please Refer Dockerfile User Documentation
The USER instruction sets the user name or UID to use when running the
image and for any RUN, CMD and ENTRYPOINT instructions that follow it
in the Dockerfile.
NOTE : Ensures that bash is the default shell.
If default shell is /bin/sh you can do like:
RUN ln -sf /bin/bash /bin/sh
RUN useradd -ms /bin/bash vault
To add group and to associate a new user, use code below.
FROM <base image>
RUN groupadd -g 2000 go \
&& useradd -m -u 2001 -g go go
USER go
OR
RUN addgroup -g 1001 -S appuser && adduser -u 1001 -S appuser -G appuser
If you also want your user to have a password, use this for Alpine based-images:
FROM alpine
ARG USER=usernameThatYouWant
ARG PASS="some password"
RUN adduser -D $USER && echo "$USER:$PASS" | chpasswd
The ARG lines are there so you can (optionally) choose another username and password when building the image (without having to change the Dockerfile).
-D so that adduser doesn't set a password just yet.Without this option adduser would become interactive and ask for a password. It doesn't accept this from the regular STDIN, so piping the password is also not an option.
echo "$USER:$PASS" | chpasswd to finally set the password.
Note that I do not set a shell with -s /path/to/some/shell in adduser because Alpine only has ash and sh available. Both of these are just symlinks to busybox anyway.(But if you are going to install another shell in your image you probably do want to use it.)
For Ubuntu-based images use this:
FROM ubuntu
ARG USER=usernameThatYouWant
ARG PASS="some password"
RUN useradd -m -s /bin/bash $USER && echo "$USER:$PASS" | chpasswd
I am using:
useradd because here this is the program for non-interactive usage.
-m so that we the user has a homedir.
-s /bin/bash so that the user has bash as default shell.
(For most other base-images you will also need to use the Ubuntu-method )

Resources