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

标签 docker dockerfile

我正在从我的 docker 镜像启动容器,如下所示:

$ 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 中指定它的原因。

提前致谢。

最佳答案

当容器内的/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 的原因是因为他们将文件从主机挂载到容器中作为主机卷,并希望权限在两者之间无缝连接。在这种情况下,我的解决方案是以 root 身份启动容器并使用调用脚本的入口点,例如:
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 中包含的修复权限脚本。 .发生的事情是将容器内用户的 uid 与挂载到容器中的文件或目录的 uid(作为卷)进行比较。当这些 id 不匹配时,容器内的用户被修改为具有与卷相同的 uid,并且容器内具有旧 uid 的所有文件都将被更新。我的入口点的最后一步是调用类似的东西:
exec gosu app_user "$@"

这有点像作为 app_user 运行“CMD”值的 su 命令,但有一些 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)到镜像中,或者您没有在生产中安装主机卷)。

关于docker - 如何在docker容器中正确使用系统用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50658883/

相关文章:

Docker:无法从 Windows 登录 Docker Hub

haskell - tf-random不会安装在Docker容器中

docker - Docker容器未保存状态

javascript - 当我想要 dockerize 我的 nextjs 项目时出现问题

docker - 在docker文件中使用if循环

docker - 在 amd64 linux 机器上为 arm32v7 容器运行 docker build 时出错 : standard_init_linux. go:207

docker - 如何在本地机器上查找docker镜像

amazon-web-services - 如何使用efsVolumeConfiguration任务定义参数Beta(由AWS于2020年1月启动)在ECS集群上安装EFS

docker - Dockerfile变量的if else子句不起作用

python - 构建docker镜像时无法运行requirements.txt文件