我已经configuration了一个运行代码的OpenSuse 42.3 docker镜像。 该图像有一个名为“myuser”的用户(非root用户),通过Dockerfile在初始Image生成期间创build。 我有三个脚本文件,根据用户所在的操作系统从映像生成一个容器。
问题 :容器中的用户名“myuser”是否可以设置为执行容器生成脚本的用户的用户名?
我的目标是让用户以交互方式popup容器并能够从容器内运行代码。 代码只是一个单独的执行并具有一些IO的二进制文件,所以我希望用户的目录可以从容器中访问,以便他们可以导航到他们机器上的文件夹并运行代码在文件系统中生成输出。
以下是我迄今为止所构build的。 我试图在linux脚本调用docker run
期间设置USER环境variables,但是这并没有将用户从“myuser”更改为“bob”(启动容器的主机上的用户名)。 目录的安装似乎工作正常。 我不确定是否有可能实现我的目标。
Linux容器脚本:
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容器脚本:
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容器脚本:
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"
下面的代码已经被检入https://github.com/bmitch3020/run-as-user 。
我将在一个入口点.sh处理这个问题,它检查/ home / myuser的所有权,并更新容器内的用户的uid / gid。 它可以看起来像这样:
#!/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 "$@"
以下是相关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
然后运行它,你只需要将/ home / myuser挂载为一个卷,它将调整入口点的权限。 例如:
$ docker build -t run-as-user . $ docker run -it --rm -v $(pwd):/home/myuser run-as-user /bin/bash
在这个容器里面,你可以运行id
和ls -l
来查看你是否可以访问/ home / myuser文件。
用户名不重要。 重要的是uid和gid的价值。
用户myuser在你的容器里将有一个1000(第一个非root用户ID)的uid。 因此,当你启动你的容器并从主机看容器进程时,你将会看到容器被拥有主机上1000的用户拥有。
您可以通过指定用户,一旦你运行你的容器使用以下来覆盖:
docker run --user 1001 ...
因此,如果您希望容器中的用户能够访问拥有1005用户的主机上的文件,只需使用–user 1005运行容器即可。
为了更好地理解用户在容器和主机之间的映射关系,请看这篇精彩的文章。 https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf
首先( https://docs.docker.com/engine/reference/builder/#arg ):
警告:建议不要使用构建时变量来传递github密钥,用户凭据等秘密。使用docker history命令,构建时变量值对图像的任何用户都是可见的。
但是,如果你仍然需要这样做,请阅读https://docs.docker.com/engine/reference/builder/#arg :
Dockerfile可能包含一个或多个ARG指令。 例如,以下是一个有效的Dockerfile:
FROM busybox ARG user1 ARG buildno ...
和https://docs.docker.com/engine/reference/builder/#user :
USER指令设置用户名(或UID)和可选的用户组(或GID)在运行映像时以及在Dockerfile中执行的任何RUN,CMD和ENTRYPOINT指令。
USER <user>[:<group>] or USER <UID>[:<GID>]