我如何使用"docker run --user"但具有根权限



我有一个包含分析管道的Docker镜像。若要运行此管道,我需要提供输入数据,并且希望保留输出。此管道必须能够由我以外的其他用户在他们自己的笔记本电脑上运行。

简而言之,我的根 (/( 文件夹结构如下:

total 72
drwxr-xr-x   1 root   root 4096 May 29 15:38 bin
drwxr-xr-x   2 root   root 4096 Feb  1 17:09 boot
drwxr-xr-x   5 root   root  360 Jun  1 15:31 dev
drwxr-xr-x   1 root   root 4096 Jun  1 15:31 etc
drwxr-xr-x   2 root   root 4096 Feb  1 17:09 home
drwxr-xr-x   1 root   root 4096 May 29 15:49 lib
drwxr-xr-x   2 root   root 4096 Feb 24 00:00 lib64
drwxr-xr-x   2 root   root 4096 Feb 24 00:00 media
drwxr-xr-x   2 root   root 4096 Feb 24 00:00 mnt
drwxr-xr-x   1 root   root 4096 Mar 12 19:38 opt
drwxr-xr-x   1 root   root 4096 Jun  1 15:24 pipeline
dr-xr-xr-x 615 root   root    0 Jun  1 15:31 proc
drwx------   1 root   root 4096 Mar 12 19:38 root
drwxr-xr-x   3 root   root 4096 Feb 24 00:00 run
drwxr-xr-x   1 root   root 4096 May 29 15:38 sbin
drwxr-xr-x   2 root   root 4096 Feb 24 00:00 srv
dr-xr-xr-x  13 root   root    0 Apr 29 10:14 sys
drwxrwxrwt   1 root   root 4096 Jun  1 15:25 tmp
drwxr-xr-x   1 root   root 4096 Feb 24 00:00 usr
drwxr-xr-x   1 root   root 4096 Feb 24 00:00 var

管道脚本位于/pipeline 中,并在我的 Dockerfile 中使用"COPY./pipeline"指令打包到映像中。

出于各种原因,设置此管道(这是旧管道(时,输入数据必须位于/pipeline/project等文件夹中。为了运行我的管道,我使用:

docker run --rm --mount type=bind,source=$(pwd),target=/pipeline/project --user "$(id -u):$(id -g)" pipelineimage:v1

换句话说,我将一个包含数据的文件夹挂载到/pipeline/project。我发现我需要使用 --user 来确保输出文件具有正确的权限 - 即在容器退出后,我将在我的主机上具有读/写/exec 访问权限。

管道运行,但我有一个问题:管道使用的一个特定软件自动尝试在$HOME中生成(我无法更改(1 个文件夹(所以我上面显示了/- (和我的 WORKDIR 中的 1 个文件夹(我已经在我的 Dockerfile 中设置为/pipeline(。这些尝试失败了,我猜这是因为我没有以 root 身份运行管道。但是我需要使用 --user 来确保我的输出具有正确的权限 - 即我不需要 sudo 权限来读取这些输出等。

我的问题是:我该如何处理这个问题?似乎通过使用--user,我为成功制作了许多输出文件的挂载文件夹(/pipeline/projects(设置了正确的权限,没有问题。但是,如何确保在该挂载之外正确制作其他 2 个文件夹?

我尝试了以下方法,但没有成功:

  • 正在执行"COPY -chown myhostuid:mygroupid" . pipeline/"。这有效,但我必须对我的 uid 和 gid 进行硬编码,以便在其他同事尝试运行图像时不起作用。
  • 添加一个具有 sudo 权限的新用户并使其运行映像:"RUN useradd -r newuser -g sudo"(我也尝试使用"root"组但没有成功(。这只是给了我需要 sudo 权限才能读/写/执行的输出。这不是我想要的。

我错过了什么吗?我不明白为什么处理挂载文件夹的权限"容易",而处理容器中其他文件夹的权限却要困难得多。谢谢。

如果您的软件不依赖于相对路径(~/./(,您只需将$HOMEWORKDIR设置为任何用户都可以写入的目录:

ENV HOME=/tmp
WORKDIR /tmp

如果你不能做到这一点,你可以通过环境将 uid/gid 传递给以 root 身份运行的入口点脚本,根据需要使用 chown/chmod,然后删除运行管道的权限(runusersusudosetuidgid(。

例如(未经测试(:

entrypoint.sh

#!/bin/bash
[[ -v "RUN_UID" ]] || { echo "unset RUN_UID" >&2; exit 1; }
[[ -v "RUN_GID" ]] || { echo "unset RUN_GID" >&2; exit 1; }
# chown, chmod, set env, etc.
chown $RUN_UID:$RUN_GID "/path/that/requires/write/permissions"
export HOME=/tmp
# Run the pipeline as a non-root user.
sudo -E -u "#$RUN_UID" -g "#$RUN_GID" /path/to/pipeline

Dockerfile

...
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

最后,在运行时通过环境传递用户和组 ID:

docker run --rm --mount type=bind,source=$(pwd),target=/pipeline/project -e RUN_UID=$(id -u) -e RUN_GID=$(id -g) pipelineimage:v1

最新更新