如何在docker容器中正确使用系统用户

时间:2018-06-02 16:21:22

标签: docker dockerfile

我从我的码头图片中启动容器,如下所示:

$ docker run -it --rm --user=999:998 my-image:latest bash

其中uid和gid适用于名为sdp的系统用户:

$ id sdp uid=999(sdp) gid=998(sdp) groups=998(sdp),999(docker)

但是:容器说"没有" ...

groups: cannot find name for group ID 998
I have no name!@75490c598f4c:/home/myfolder$ whoami
whoami: cannot find name for user ID 999

我做错了什么?

请注意,我需要在多个系统上基于此映像运行容器,并且不能保证用户的uid:gid在系统中是相同的,这就是我需要在命令行而不是在命令行中指定它的原因。 Dockerfile。

提前致谢。

3 个答案:

答案 0 :(得分:1)

当容器内的/ etc / passwd或/ etc / group文件中不存在uid / gid时,将发生此类错误。有多种解决方法。一种是使用类似以下的命令将这些文件从主机直接映射到容器中:

$ docker run -it --rm --user=999:998 \
  -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro \
  my-image:latest bash

我不喜欢该解决方案,因为容器文件系统中的文件现在可能具有错误的所有权,从而导致潜在的安全漏洞和错误。

通常,人们想要更改容器内的uid / gid的原因是因为他们正在将文件从主机作为主机卷装载到容器中,并且希望权限在两者之间是无缝的。在这种情况下,我的解决方案是以根用户身份启动容器,并使用调用脚本的入口点,例如:

if [ -n "$opt_u" ]; then
  OLD_UID=$(getent passwd "${opt_u}" | cut -f3 -d:)
  NEW_UID=$(stat -c "%u" "$1")
  if [ "$OLD_UID" != "$NEW_UID" ]; then
    echo "Changing UID of $opt_u from $OLD_UID to $NEW_UID"
    usermod -u "$NEW_UID" -o "$opt_u"
    if [ -n "$opt_r" ]; then
      find / -xdev -user "$OLD_UID" -exec chown -h "$opt_u" {} \;
    fi
  fi
fi

以上内容来自我包含在base image中的Fix-Perms脚本。将容器内部用户的uid与安装在容器中(作为卷)的文件或目录的uid进行比较。如果这些ID不匹配,则将容器内的用户修改为具有与该卷相同的uid,并使用旧uid更新容器内的任何文件。我的入口点的最后一步是调用以下内容:

exec gosu app_user "$@"

有点像su命令,以app_user的身份运行“ CMD”值,但是带有一些exec逻辑,用“ CMD”进程替换了pid 1,以便更好地处理信号。然后,我使用以下命令运行它:

$ docker run -it --rm --user=0:0 -v /host/vol:/container/vol \
  -e RUN_AS app_user --entrypoint /entrypoint.sh \
  my-image:latest bash

看看我链接到的基本映像回购,包括使用nginx的示例,该示例显示了这些部件如何装配在一起,并避免了在生产环境中以root身份运行容器的需要(假设生产已知uid / gid可以烘焙到映像中,或者您不将主机卷挂载到生产环境中。

答案 1 :(得分:0)

1)确保用户999在当前目录上具有正确的特权,您需要在docker文件中尝试类似的操作     来自

RUN mkdir /home/999-user-dir && \
    chown -R 999:998 /home/999-user-dir
WORKDIR /home/999-user-dir
USER 999

尝试在不使用用户参数的情况下使用此图片旋转容器,看看是否可行。

2)其他原因可能是以下文件的权限问题,请确保您的群组998对这些文件具有读取权限

-rw-r--r-- 1 root root 690 Jan 2 06:27 /etc/passwd -rw-r--r-- 1 root root 372 Jan 2 06:27 /etc/group

谢谢

答案 2 :(得分:0)

因此,在您的主机上,您可能会看到您的用户和组:

$ cat /etc/passwd
sdp:x:999:998::...

但是在容器中,您不会在/etc/passwd中看到它们。

这是预期的行为,只要您不将/etc/passwd文件装入容器内部(并且从安全性的角度考虑,不要这样做),主机和容器就会完全分开。 />

现在,如果您在Dockerfile中指定了默认用户,则--user运算符将覆盖USER指令,因此您在容器内没有用户名称,但是请请注意,指定uid:gid选项意味着容器在主机中具有与用户相同的uid值的用户权限。

现在请求您不要在Dockerfile中指定用户-这应该不成问题。只要uid与主机上的现有用户uid匹配,就可以像在运行时一样进行设置。

如果必须以特权模式运行某些容器-请考虑使用user namespace