Exec 未替换 Docker 入口点脚本中的 bash shell

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

我已经尝试了 execsu-exec 的一些变体,但我仍然会遇到上述情况。我需要在启动时向 UWSGI 提供我的 PEM 密码,所以我一直在使用这样的语法:

echo $PEM_PASSPHRASE | exec uwsgi --ini /opt/mysite/uwsgi.ini

起床和 运行ning 工作正常,但我仍然得到 PID 1 /bin/bash 进程 运行ning,UWSGI 进程作为下面的子进程。我觉得我遗漏了一些明显的细节,无法通过 exec.

将 bash 进程替换为 UWSGI 进程

为了它的价值,我只在 Docker 文件中使用 ENTRYPOINT,而不是 CMD:

ENTRYPOINT ["docker-entrypoint.sh"]

任何正确方向的指示都将不胜感激。

你的那个命令应该放在 ENTRYPOINT 那么,因为它的命令将是第一个进程。 (我假设您是从 docker-entrypoint.sh 内部调用它的)

ENTRYPOINT ["echo $PEM_PASSPHRASE | exec uwsgi --ini /opt/mysite/uwsgi.ini"]

Shell 管道中的命令——包括 exec——子 shell 中的 运行。因此,echo ... | exec uwsgi ... 创建了两个子进程,一个 运行ning echo (实际上可能是一个 subshell 运行ning shell 内置),另一个subshell 立即替换为 uwsgi.

我没有在 docker 中对此进行测试,但以下任一方法都应该有效:

exec uwsgi --ini /opt/mysite/uwsgi.ini <<<"$PEM_PASSPHRASE"
exec uwsgi --ini /opt/mysite/uwsgi.ini < <(echo "$PEM_PASSPHRASE")

写到这里,突然想到在bashv4.3及以后的版本中,其实更简单,因为lastpipeshell选项会告诉bash 到 运行 当前 shell 中管道的最后一个元素,而不是子 shell:

shopt -s lastpipe
echo "$PEM_PASSPHRASE" | exec uwsgi --ini /opt/mysite/uwsgi.ini

但是,由于这是我们正在讨论的密码,因此存在关于这些可能如何暴露密码的安全考虑。第一个选项 (a "here-string") 创建一个临时文件(在磁盘上!)存储密码,打开它进行输入,然后立即取消链接。这意味着它在任何正常文件路径下都不可访问,但它会无限期地存储在磁盘上(并且不会被安全删除)。可以物理访问计算机的人(或在某些系统上,可通过 /proc 直接读取)。所以不太好。

(这里的文档会做同样的事情。)

第二个(从 "process substitution" 重定向)和第三个 (lastpipe) 可能更好……或更糟。在 bash 中,echo 是内置的,因此进程替换(<( ) 部分)创建了一个子 shell,运行 是 echo内置)进入管道......然后退出。哪个更好。但是在没有内置 echo 的 shell 中,它将 运行 一个单独的 echo 进程,并且它的参数列表(即密码)实际上是 public信息(例如通过 ps 命令)。这可能更糟。

所以我的建议是使用第二个或第三个,并确保你运行在bash下使用它。