[英]Exec not replacing bash shell in Docker entrypoint script
我正在尝试从 Docker 容器运行 UWSGI 服务器。 我已经成功了,但我遇到了一个问题,因为在容器启动后,我的入口点脚本仍将以 root 身份运行,PID 为 1,而我宁愿将初始/bin/bash
进程替换为 UWSGI 进程:
bash-4.4# ps aux
PID USER TIME COMMAND
1 root 0:00 {docker-entrypoi} /bin/bash /usr/local/bin/docker-entrypoint.sh
19 myuser 0:00 uwsgi --ini /opt/mysite/uwsgi.ini
21 myuser 0:00 uwsgi --ini /opt/mysite/uwsgi.ini
22 myuser 0:00 uwsgi --ini /opt/mysite/uwsgi.ini
24 myuser 0:02 python3 ./manage.py qcluster
28 myuser 0:00 python3 ./manage.py qcluster
29 myuser 0:00 python3 ./manage.py qcluster
30 myuser 0:00 python3 ./manage.py qcluster
31 myuser 0:00 python3 ./manage.py qcluster
32 myuser 0:00 python3 ./manage.py qcluster
33 myuser 0:00 python3 ./manage.py qcluster
34 myuser 0:00 python3 ./manage.py qcluster
我已经尝试了exec
和su-exec
一些变体,但我仍然遇到了上述问题。 我需要在启动时向 UWSGI 提供我的 PEM 密码,所以我一直在使用这样的语法:
echo $PEM_PASSPHRASE | exec uwsgi --ini /opt/mysite/uwsgi.ini
这可以很好地启动和运行,但我仍然让 PID 1 /bin/bash
进程运行,UWSGI 进程作为下面的子进程。 我觉得我错过了一些明显的细节,无法通过exec
将 bash 进程替换为 UWSGI 进程。
对于它的价值,我只在 Dockerfile 中使用 ENTRYPOINT,而不是 CMD:
ENTRYPOINT ["docker-entrypoint.sh"]
任何指向正确方向的指针将不胜感激。
管道中的 Shell 命令——包括exec
在子 shell 中运行。 因此, echo ... | exec uwsgi ...
echo ... | exec uwsgi ...
创建两个子进程,一个运行echo
(实际上可能是一个运行 shell 内置的子shell),另一个子shell 会立即用uwsgi
替换自己。
我还没有在 docker 中测试过这个,但以下任一方法都应该有效:
exec uwsgi --ini /opt/mysite/uwsgi.ini <<<"$PEM_PASSPHRASE"
exec uwsgi --ini /opt/mysite/uwsgi.ini < <(echo "$PEM_PASSPHRASE")
写完这篇之后,我突然想到在 bash v4.3 及更高版本中,它实际上更容易,因为lastpipe
shell 选项将告诉 bash 在当前 shell 中运行管道的最后一个元素,而不是在子 shell 中:
shopt -s lastpipe
echo "$PEM_PASSPHRASE" | exec uwsgi --ini /opt/mysite/uwsgi.ini
但是,由于这是我们正在讨论的密码,因此存在关于这些密码如何公开的安全考虑。 第一个选项(“here-string”)创建一个临时文件(在磁盘上!)存储密码,打开它输入,然后立即取消链接。 这意味着它在任何普通文件路径下都无法访问,但它会无限期地存储在磁盘上(并且不会被安全删除)。 可以物理访问计算机的人(或在某些系统上,可直接通过 /proc 读取)。 所以不太好。
(here-document 会做同样的事情。)
第二个(从“进程替换”重定向)和第三个( lastpipe
)可能更好......或更糟。 在 bash 中, echo
是一个内置函数,因此进程替换( <( )
部分)会创建一个运行echo
内置函数的子外壳程序)到管道中……然后退出。 哪个更好。 但是在没有内置echo
shell 中,它将运行一个单独的echo
进程,并且它的参数列表(即密码)实际上是公共信息(例如,通过ps
命令)。 这可能更糟。
所以我的建议是使用第二个或第三个,并确保你在 bash 下运行它。
你的那个命令应该被放置为ENTRYPOINT
,因为它的命令将是第一个进程。 (我假设您是从docker-entrypoint.sh
内部调用它的)
ENTRYPOINT ["echo $PEM_PASSPHRASE | exec uwsgi --ini /opt/mysite/uwsgi.ini"]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.