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?
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
scriptThis 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.
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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With