3

我正在尝试从 Docker 容器运行 UWSGI 服务器。我已经取得了成功,但我遇到了一个问题,因为我的入口点脚本在容器启动后仍将以 PID 1 的 root 身份运行,而我宁愿将初始/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

我用execand尝试了一些变化su-exec,但我仍然在上面。我需要在启动时向 UWSGI 提供我的 PEM 密码,所以我一直在使用如下语法:

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

这可以很好地启动和运行,但我仍然让 PID 1/bin/bash进程运行,UWSGI 进程作为下面的子进程。我觉得我错过了一些明显的细节来实际让 bash 进程被 UWSGI 进程通过exec.

对于它的价值,我只在 Dockerfile 中使用 ENTRYPOINT,而不是 CMD:

ENTRYPOINT ["docker-entrypoint.sh"]

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

4

2 回答 2

4

管道中的 shell 命令——包括exec——在子 shell 中运行。因此,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 及更高版本中,它实际上更容易,因为lastpipeshell 选项将告诉 bash 在当前 shell 中运行管道的最后一个元素,而不是子 shell:

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

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

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

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

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

于 2020-01-03T23:49:20.840 回答
0

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

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

于 2020-01-03T22:23:42.450 回答