Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

docker: set running user while launch container

Tags:

I use the official golang docker image to compile my go program and put the resulting executable on a volume mapped to my host directory.

The problem is that file generated by docker belongs to root:root, which is very annoying because I do not want to run my script via sudo.

I searched for solutions to make docker container run as non-root, but the method I found need to change Dockerfile and add user to the image, e.g.

http://gbraad.nl/blog/non-root-user-inside-a-docker-container.html

Is there a way to make docker container run as the CURRENT user on host machine, i.e., user A runs this image will generate file belongs to A:A, and user B generate file belongs to B:B, while A and B are both users defined on host machine (i.e. where the volume resides), without the need to add A and B into the image via Dockerfile?

like image 870
xrfang Avatar asked Dec 08 '17 00:12

xrfang


2 Answers

I was able to fabricate a "solution" to this problem. It's a little bit crude, but it as far as I can tell at the moment, it gets the job done without installing the user into the image.
Essentially, I am using libnss-wrapper in conjunction with a custom-made run_as_user script, which I am in turn using to alias those commands that cause me trouble for my unknown UID (such as ssh).

Dockerfile

FROM whatever
RUN apt-get update && apt-get install -y libnss-wrapper
COPY run_as_user /usr/local/bin/
RUN chmod a+x /usr/local/bin/run_as_user

# copy some command aliases that need to be early on the path
COPY ssh /usr/local/sbin
RUN chmod a+x /usr/local/sbin/ssh

run_as_user script

This script creates a passwd and group file based on the current user's UID and GID, and then uses that to parameterize libnss-wrapper

#!/bin/sh
# run a command as (non-existent) user, using libnss-wrapper

U=`id -u`
G=`id -g`

HOME_DIR=/tmp/user
PASSWD=/var/tmp/passwd
GROUP=/var/tmp/group

if [ ! -d "$HOME_DIR" ]; then
  mkdir "$HOME_DIR"
fi
if [ ! -f "$PASSWD" ]; then
  echo "user::$U:$G::$HOME_DIR:" > "$PASSWD"
fi
if [ ! -f "$GROUP" ]; then
  echo "user::$G:" > "$GROUP"
fi

LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_PASSWD="$PASSWD" NSS_WRAPPER_GROUP="$GROUP" "$@"

ssh alias script

#!/bin/sh
SSH=/usr/bin/ssh
/usr/local/bin/run_as_user "$SSH" "$@"

Again, this works because /usr/local/sbin is first on my path.

So far this has been working for me. If there are (severe) issues with this, I'd be happy to have them pointed out to me.

like image 86
derabbink Avatar answered Sep 21 '22 13:09

derabbink


which I made by base alphine-golang plus the git tool), runs on my laptop with the -u arg, but if I run it on an debian virtual machine, it tells me No user exists for uid 1001

Ideally, you would make your own image (based on an existing one) with the right expected ID:

RUN useradd -r -u 1001 -g appuser appuser
USER appuser

See "Understanding how uid and gid work in Docker containers", from Marc Campbell:

UID/GID wiht Docker


The OP adds:

I understand the reason because this is exactly what I try to avoid: add user into the image.
If my problem was not solved, I will try to modify the container directly.

Actually, there is another alternative, which allows you to not modify an image and not add a user: userns or user remap (since docker 1.10). However, as I mention here, you would need docker 17.06 to avoid some bugs.

like image 38
VonC Avatar answered Sep 21 '22 13:09

VonC