如何在Docker容器中一个接一个地运行多个入口点脚本? [英] How to run multiple entrypoint scripts one after another inside docker container?

查看:129
本文介绍了如何在Docker容器中一个接一个地运行多个入口点脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将主机UID与容器UID进行如下匹配.

I am trying to match the host UID with container UID as below.

Dockerfile

Dockerfile

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"]

entrypoint.sh

entrypoint.sh

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调用.

Please note the output of whoami above. Even If I changed the UID of deploy to host uid, the entrypoint script process doesn't get changed as the entrypoint shell has been called by UID 1000.

因此,我提出了一个解决方案,使两个入口点脚本一个是更改UID,另一个是用于容器的引导过程,该过程将在更改部署的UID后在单独的外壳中运行.因此,如何使两个入口点依次运行.例如类似

So I came up in a solution to make two entry point script one is to change the UID and another one is for container's bootstrap process which will be run in a separate shell after I change the UID of deploy. So how can I make two entrypoint run after another. E.g something like

ENTRYPOINT ["/fix-uid.sh&&/entrypoint.sh"]

推荐答案

似乎您正在设计一种与我创建的解决方案非常相似的解决方案.正如ErikMD提到的,不要使用gosu从用户切换到root,而是要从root切换到用户.否则,您的容器内将出现一个开放的安全漏洞,任何用户都无法成为root用户,从而破坏了以不同的用户ID运行容器的目的.

It looks like you're designing a solution very similar to one that I've created. As ErikMD mentions, do not use gosu to switch from a user to root, you want to go the other way, from root to a user. Otherwise, you will have an open security hole inside your container than any user can become root, defeating the purpose of running a container as a different user id.

对于我提出的解决方案,无论容器是在没有卷挂载的情况下仅在生产环境中运行,还是在最初通过以根用户身份启动容器的情况下在带有卷挂载的开发环境中运行,都可以使用.您可以拥有一个相同的Dockerfile,并更改入口点以使其具有以下含义:

For the solution that I put together, I have it work whether the container is run in production as just a user with no volume mounts, or in development with volume mounts by initially starting the container as root. You can have an identical Dockerfile, and change the entrypoint to have something along the lines of:

#!/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 脚本为

The fix-perms script above is from my base image, and includes the following bit of code:

# 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上利用它我现在在里面的命令.)

(Note, I really like your use of stat -c and will likely be updating my fix-perms script to leverage that over the ls command I have in there now.)

最重要的部分是运行容器.当您需要运行 fix-perms 代码(对我来说,这仅在开发中)时,我将以root身份启动容器.这可以是撰写文件中的 docker run -u root:root ... user:"root:root" .这首先将容器作为根启动,这会在运行 fix-perms 的入口点触发if/else的前半部分,然后运行 gosu deploy 从根目录删除在调用作为命令(CMD)的"$ @"之前进行部署.最终结果是容器中的pid 1现在以部署用户的身份运行您的命令.

The important part to this is running the container. When you need the fix-perms code to run (which for me is only in development), I start the container as root. This can be a docker run -u root:root ... or user: "root:root" in a compose file. That launches the container as root initially, which triggers the first half of the if/else in the entrypoint that runs fix-perms and then runs a gosu deploy to drop from root to deploy before calling "$@" which is your command (CMD). The end result is pid 1 in the container is now running your command as the deploy user.

顺便说一句,如果您真的想以一种易于扩展子图像的方式来运行多个入口点片段的简便方法,那么我将使用一个由入口点处理的 entrypoint.d 文件夹基本图片中的脚本.编写代码以实现该逻辑很简单:

As an aside, if you really want an easier way to run multiple entrypoint fragments in a way that's easy to extend with child images, I use an entrypoint.d folder that is processed by an entrypoint script in my base image. To code to implement that logic is as simple as:

for ep in /etc/entrypoint.d/*.sh; do
  if [ -x "${ep}" ]; then
    echo "Running: ${ep}"
    "${ep}"
  fi
done


所有这些以及使用nginx的示例都可以在以下位置看到: https://github.com/sudo-bmitch/docker-base

这篇关于如何在Docker容器中一个接一个地运行多个入口点脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆