Dockerfile 将主机用户 UID 和 GID 复制到镜像

Posted

技术标签:

【中文标题】Dockerfile 将主机用户 UID 和 GID 复制到镜像【英文标题】:Dockerfile replicate the host user UID and GID to the image 【发布时间】:2017-11-24 18:31:55 【问题描述】:

类似于SO post about replicating UID/GID in container from host,但是如何使用具有复制 UID 和 GID 的用户构建映像?最好,你如何使用 dockerfile 来做这件事?

我可以使用 bash 脚本来完成:

#!/bin/bash

# current uid and gid
curr_uid=`id -u`
curr_gid=`id -g`

# create bb.dockerfile:
cat << EOF1 > bb.dockerfile
 FROM ubuntu:xenial-20170214
 ARG UNAME=testuser
EOF1

 echo ARG UID=$curr_uid >> bb.dockerfile
 echo ARG GID=$curr_gid >> bb.dockerfile

cat << EOF2 >> bb.dockerfile
 RUN groupadd -g \$GID \$UNAME
 RUN useradd -m -u \$UID -g \$GID -s /bin/bash \$UNAME
 USER \$UNAME
 CMD /bin/bash
EOF2

docker build -f bb.dockerfile -t testimg .

这个 bash 将生成一个如下所示的 docker 文件并在其上构建。

 FROM ubuntu:xenial-20170214
 ARG UNAME=testuser
 ARG UID=1982
 ARG GID=1982
 RUN groupadd -g $GID $UNAME
 RUN useradd -m -u $UID -g $GID -s /bin/bash $UNAME
 USER $UNAME
 CMD /bin/bash

我要的是从 dockerfile 中删除硬编码的主机 UID 1982 和 GID 1982。

【问题讨论】:

【参考方案1】:

您可以将其作为构建参数传递。你的 Dockerfile 可以是静态的:

FROM ubuntu:xenial-20170214
ARG UNAME=testuser
ARG UID=1000
ARG GID=1000
RUN groupadd -g $GID -o $UNAME
RUN useradd -m -u $UID -g $GID -o -s /bin/bash $UNAME
USER $UNAME
CMD /bin/bash

然后您将在构建命令中传递选项:

docker build --build-arg UID=$(id -u) --build-arg GID=$(id -g) \
  -f bb.dockerfile -t testimg .

请注意,我已经以不同的方式解决了与此类似的问题,方法是以 root 身份运行一个入口点,该入口点查看主机卷挂载的文件/目录权限,并调整容器内用户的 uid/gid 以匹配卷 uid/gid。进行该更改后,它会放弃从 root 用户到修改后的 uid/gid 用户的访问权限,并运行原始命令/入口点。结果是图像可以在任何开发人员机器上不变地运行。这方面的一个例子可以在我的 jenkins-docker repo 中找到:

https://github.com/sudo-bmitch/jenkins-docker

【讨论】:

我不明白,命令行中的 UID 和 GID 参数是否会隐藏/覆盖“静态”Dockerfile 条目? 在我的 docker 容器 ubuntu guest 中,gid 20 属于拨出。通常应该为您在主机上的用户帐户分配其自己的组 id,而不是重复使用 20。如果您运行 id -g,您会得到 20 吗? id -u 得到什么? @AlexanderMills 我猜你可能在 guid 20 = 员工的 macos 上运行,但来宾是一些 20 = 其他东西的 linux。这种传递组 ID 并创建组的想法似乎只有在组不存在时才有意义,这在 linux 主机上就是这种情况,通常您的 GID 将是一个只包含您自己的组。 @AlexanderMills 是的,dockerfile 中 docker args 的默认值会被 build 命令覆盖。如果容器中已经存在 uid/gid,您可以添加 -o 选项以允许非唯一 id。 干净的答案,它解决了 docker 的很多问题。尤其是在使用 jenkins 启动 docker 时..【参考方案2】:

最终bb.bash 看起来像:

#!/bin/bash

# current uid and gid
curr_uid=`id -u`
curr_gid=`id -g`

# create bb.dockerfile:
cat << EOF2 > bb.dockerfile
 FROM ubuntu:xenial-20180417
 ARG UNAME=testuser
 ARG UID=1000
 ARG GID=1000
 RUN groupadd -g \$GID \$UNAME
 RUN useradd -m -u \$UID -g \$GID -s /bin/bash \$UNAME
 USER \$UNAME
 CMD /bin/bash
EOF2    

docker build --build-arg UID=$curr_uid --build-arg GID=$curr_gid \
    -f bb.dockerfile -t testimg .

然后另一个脚本是创建容器:

#!/bin/bash

docker run -it -d -v $(pwd)/shared:/home/testuser/shared \
    --name testcontainer -P testimg

【讨论】:

还创建了一个 docker 文件和脚本以通过 ssh 运行 X:参见 superuser SO "Run JetPack TX2 Installer in a Docker Container"。

以上是关于Dockerfile 将主机用户 UID 和 GID 复制到镜像的主要内容,如果未能解决你的问题,请参考以下文章

理解 docker 容器中的 uid 和 gid

VirtualBox for Apache 中的共享文件夹

如何将文件从 dockerfile 复制到主机?

将主机的环境变量传递给 dockerfile

Docker 将文件从 dockerfile 复制到主机

将文件夹从 Dockerfile 复制到主机 [重复]