【问题标题】:Docker: executing all commands as local user and not rootDocker:以本地用户而不是root用户身份执行所有命令
【发布时间】:2019-07-01 22:47:15
【问题描述】:

如何运行docker rundocker-compose up/run 命令,以便docker 内的进程由与我的本地用户具有相同uuid 的用户运行?

我需要这样做,以便“内部 docker”进程生成的任何文件都具有我的本地用户的所有权权限。

复制:

使用alpine:3.9 容器,挂载到要写入的文件的卷中并创建文件。假设我当前的用户名是user

mkdir output_dir #Create an output directory
docker run -it --rm --volume "/path/to/output_dir:/tmp" alpine:3.9 touch /tmp/file.txt
ls -la output_dir/file.txt

会给出输出:

-rw-r--r-- 1 root root 0 Feb  7 19:51 /path/to/output_dir/file.txt

这意味着我需要sudo chown user:user /path/to/output_dir/file.txt 才能以当前用户身份访问我自己的文件系统。

如果没有这个额外的步骤,我该怎么做?

想到的想法:

添加一个 Docker Entrypoint,它将在容器内创建一个与我的本地用户具有相同 uuid 的用户,并以该用户身份执行任何代码。

docker-entrypoint.sh

#!/bin/sh
TEMP_UID="${TEMP_UID:-1000}"
set -ux
useradd -s /bin/false --no-create-home -u ${TEMP_UID} temp
#su-exec is an executable which makes it easy to run a process as a specific user.
exec su-exec temp $@

问题是我必须在每个docker run 命令中注入TEMP_UID=<user_id> 作为环境变量,或者为每个docker-compose up/run 命令包含在我的docker-compose.yml 文件中。如果Docker 有一个内部变量来跟踪运行它的用户的uuid,我会使用它。但我似乎找不到这样的内部变量。

任何帮助将不胜感激!

【问题讨论】:

标签: docker dockerfile file-permissions user-permissions


【解决方案1】:

我认为答案很简单

docker run --user ${UID} -it --rm --volume "/path/to/output_dir:/tmp" alpine:3.9 touch /tmp/file.txt

请注意,我将 --user ${UID} 注入到您的示例命令中。

【讨论】:

  • 这行得通,但我想尽量避免每次都注入用户,如上一段所述
【解决方案2】:

许多当前选项需要在容器外部进行更改才能传入当前用户,或者依赖于可能并非在所有环境中都存在的变量。我的首选解决方案,因为目标是修复已安装卷上的文件权限,所以以 root 身份使用一个脚本启动入口点,该脚本更改容器用户 ID 以匹配卷安装的用户 ID。然后入口点的末尾使用 exec gosu $app_user_name "$@" 启动应用程序,以从 root 切换到在容器内修改的应用程序用户。

执行此操作的脚本在我的base image repo 中。请注意 fix-perms 脚本,其中包括如下两个部分(一个用于 uid,另一个用于 gid):

# update the uid
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

OLD_UID 值来自映像中的用户 ID,NEW_UID 来自卷挂载。如果不匹配,则运行 usermod 命令,然后运行递归 chown 命令以修复任何具有旧 uid/gid 的文件。

请注意,在生产环境中,主机上的用户 ID 可以标准化,如果需要卷,我会将主机用户 ID 与映像的用户 ID 匹配,从而允许我以该用户而不是 root 用户身份运行入口点。入口点检查当前用户 ID,如果不是 root,则跳过 fix-perms 脚​​本和 gosu 命令。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-10
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多