我正在尝试将主机UID与容器UID进行匹配,如下所示。
Docker文件
RUN addgroup -g 1000 deploy \
&& adduser -D -u 1000 -G deploy -s /bin/sh deploy
USER deploy
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
CMD ["php-fpm7","-F"]
入口点
whoami # it outputs `deploy`
# Change UID of 'deploy' as per host user UID
HOST_CURRENT_USER_ID=$(stat -c "%u" /var/www/${PROJECT_NAME})
if [ ${HOST_CURRENT_USER_ID} -ne 0 ]; then
gosu root usermod -u ${HOST_CURRENT_USER_ID} deploy
gosu root groupmod -g ${HOST_CURRENT_USER_ID} deploy
fi
whoami # It outputs as unknown user id 1000.
请注意上面
whoami
的输出。即使我将deploy的UID更改为主机uid,入口点脚本进程也不会更改,因为入口点shell已被UID 1000调用。因此,我提出了一个解决方案,使两个入口点脚本一个是更改UID,另一个是用于容器的引导过程,该过程将在更改部署的UID后在单独的 shell 中运行。因此,如何使两个入口点一个接一个地运行。例如
ENTRYPOINT ["/fix-uid.sh && /entrypoint.sh"]
最佳答案
您似乎正在设计一种与我创建的解决方案非常相似的解决方案。正如ErikMD提到的,不要使用gosu从用户切换到root,而是要从root切换到用户。否则,您的容器内将有一个开放的安全漏洞,任何用户都无法成为root用户,从而破坏了以不同的用户ID运行容器的目的。
对于我提出的解决方案,无论容器是作为没有卷安装的用户在生产中运行,还是通过最初以根用户身份启动容器而在具有卷安装的开发环境中运行,都可以使用。您可以具有相同的Dockerfile,并更改入口点以使其具有以下含义:
#!/bin/sh
if [ "$(id -u)" = "0" ]; then
fix-perms -r -u deploy -g deploy /var/www/${PROJECT_NAME}
exec gosu deploy "$@"
else
exec "$@"
fi
上面的
fix-perms
脚本是from my base image,包括以下代码:# update the uid
if [ -n "$opt_u" ]; then
OLD_UID=`getent passwd "${opt_u}" | cut -f3 -d:`
NEW_UID=`ls -nd "$1" | awk '{print $3}'`
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
(请注意,我真的很喜欢您对
stat -c
的使用,并且可能会更新我的fix-perms
脚本,以将其用于我现在在那里的ls
命令。)重要的部分是运行容器。当您需要运行
fix-perms
代码时(对我来说这仅是在开发中),我以root用户身份启动容器。撰写文件中可以是docker run -u root:root ...
或user: "root:root"
。这将首先以根用户身份启动容器,这会在运行fix-perms
的入口点触发if / else的前半部分,然后运行gosu deploy
从根目录删除以部署,然后调用命令“$ @”(CMD)。最终结果是容器中的pid 1现在以部署用户身份运行命令。顺便说一句,如果您真的想以一种更容易扩展子图像的方式运行多个入口点片段的简便方法,那么我会使用
entrypoint.d
文件夹,该文件夹由基本图像中的入口点脚本处理。编写代码以实现该逻辑很简单:for ep in /etc/entrypoint.d/*.sh; do
if [ -x "${ep}" ]; then
echo "Running: ${ep}"
"${ep}"
fi
done
可以在https://github.com/sudo-bmitch/docker-base上看到所有这些以及使用nginx的示例。
关于shell - 如何在Docker容器中一个接一个地运行多个入口点脚本?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53743212/