Docker:以本地用户身份而非root用户身份执行所有命令

时间:2019-02-07 18:15:19

标签: docker dockerfile file-permissions user-permissions

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

我需要这样做,以便由“ inside-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 $@

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

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

我认为答案很简单

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

请注意,我在您的示例命令中注入了--user ${UID}

答案 1 :(得分:1)

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

执行此操作的脚本在我的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的身份运行入口点。入口点检查当前用户标识,如果不是root用户,则跳过fix-perms脚本和gosu命令。