Thursday, April 7, 2022

[SOLVED] Set docker image username at container creation time?

Issue

I have an OpenSuse 42.3 docker image that I've configured to run a code. The image has a single user(other than root) called "myuser" that I create during the initial Image generation via the Dockerfile. I have three script files that generate a container from the image based on what operating system a user is on.

Question: Can the username "myuser" in the container be set to the username of the user that executes the container generation script?

My goal is to let a user pop into the container interactively and be able to run the code from within the container. The code is just a single binary that executes and has some IO, so I want the user's directory to be accessible from within the container so that they can navigate to a folder on their machine and run the code to generate output in their filesystem.

Below is what I have constructed so far. I tried setting the USER environment variable during the linux script's call to docker run, but that didn't change the user from "myuser" to say "bob" (the username on the host machine that started the container). The mounting of the directories seems to work fine. I'm not sure if it is even possible to achieve my goal.

Linux Container script:

username="$USER"
userID="$(id -u)"
groupID="$(id -g)"
home="${1:-$HOME}"

imageName="myImage:ImageTag"
containerName="version1Image"

docker run  -it -d --name ${containerName}  -u $userID:$groupID     \
            -e USER=${username} --workdir="/home/myuser"            \
            --volume="${home}:/home/myuser" ${imageName} /bin/bash  \

Mac Container script:

username="$USER"
userID="$(id -u)"
groupID="$(id -g)"
home="${1:-$HOME}"

imageName="myImage:ImageTag"
containerName="version1Image"

docker run  -it -d --name ${containerName}                          \
            --workdir="/home/myuser"            \
            --v="${home}:/home/myuser" ${imageName} /bin/bash  \

Windows Container script:

ECHO OFF
SET imageName="myImage:ImageTag"
SET containerName="version1Image"

docker run -it -d --name %containerName% --workdir="/home/myuser" -v="%USERPROFILE%:/home/myuser" %imageName% /bin/bash


echo "Container %containerName% was created."
echo "Run the ./startWindowsLociStream script to launch container"

Solution

The below code has been checked into https://github.com/bmitch3020/run-as-user.

I would handle this in an entrypoint.sh that checks the ownership of /home/myuser and updates the uid/gid of the user inside your container. It can look something like:

#!/bin/sh

set -x
# get uid/gid
USER_UID=`ls -nd /home/myuser | cut -f3 -d' '`
USER_GID=`ls -nd /home/myuser | cut -f4 -d' '`

# get the current uid/gid of myuser
CUR_UID=`getent passwd myuser | cut -f3 -d: || true`
CUR_GID=`getent group myuser | cut -f3 -d: || true`

# if they don't match, adjust
if [ ! -z "$USER_GID" -a "$USER_GID" != "$CUR_GID" ]; then
    groupmod -g ${USER_GID} myuser
fi
if [ ! -z "$USER_UID" -a "$USER_UID" != "$CUR_UID" ]; then
    usermod -u ${USER_UID} myuser
    # fix other permissions
    find / -uid ${CUR_UID} -mount -exec chown ${USER_UID}.${USER_GID} {} \;
fi


# drop access to myuser and run cmd
exec gosu myuser "$@"

And here's some lines from a relevant Dockerfile:

FROM debian:9
ARG GOSU_VERSION=1.10

# run as root, let the entrypoint drop back to myuser
USER root

# install prereq debian packages
RUN apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
        apt-transport-https \
        ca-certificates \
        curl \
        vim \
        wget \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Install gosu
RUN dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
    && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \
    && chmod 755 /usr/local/bin/gosu \
    && gosu nobody true

RUN useradd -d /home/myuser -m myuser
WORKDIR /home/myuser

# entrypoint is used to update uid/gid and then run the users command
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD /bin/sh

Then to run it, you just need to mount /home/myuser as a volume and it will adjust permissions in the entrypoint. e.g.:

$ docker build -t run-as-user . 
$ docker run -it --rm -v $(pwd):/home/myuser run-as-user /bin/bash

Inside that container you can run id and ls -l to see that you have access to /home/myuser files.



Answered By - BMitch
Answer Checked By - Dawn Plyler (WPSolving Volunteer)