8

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?

xrfang
  • 1,754
  • 4
  • 18
  • 36
  • 1
    Just use the `-u` flag to `docker run`. E.g., `docker run -u $UID`. – larsks Dec 08 '17 at 00:59
  • 1
    @larsks this worked. thanks! – xrfang Dec 08 '17 at 01:46
  • @larsks sometime it does NOT work. same docker image (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 – xrfang Dec 08 '17 at 03:03

2 Answers2

7

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.

derabbink
  • 2,419
  • 1
  • 22
  • 47
4

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.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • I am sorry this is NOT what I want. @larsks answer is what I expected. – xrfang Dec 08 '17 at 14:00
  • 1
    @xrfang this answer addresses your second comment, and explains how the all user id matching between host and docker container runs. – VonC Dec 08 '17 at 14:11
  • thanks 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. Fortunately, this is not necessary now. – xrfang Dec 09 '17 at 04:04
  • @xrfang OK. I have edited my answer accordingly, and I propose an alternative (avoiding any user creation) – VonC Dec 09 '17 at 07:28