为什么 uWSGI 在 Docker 无法启动?

Why does uWSGI fail to start in Docker?

我对使用 uWSGI 来服务 Python 应用程序比较陌生,我正尝试以 emperor 模式与 vassal 启动 uWSGI 进程,但每次我尝试在 [=59= 内部启动 uWSGI ] 使用以下命令(如 root):

# /usr/local/bin/uwsgi --ini /etc/uwsgi/emperor.ini

我得到的回复是:

[uWSGI] getting INI configuration from /etc/uwsgi/emperor.ini
2.0.13.1

emperor.ini 配置文件如下所示:

# files/etc/uwsgi/emperor.ini
[uwsgi]
emperor = /etc/uwsgi/apps-enabled
die-on-term = true
log-date = true

而唯一的 vassal 的配置如下:

# files/etc/uwsgi/apps-enabled/application.ini
[uwsgi]
app_dir = /var/www/server
plugin = python
master = true
callable = app
chdir = %(app_dir)
mount = /=%(app_dir)/start.py
protocol = uwsgi
socket = :8079
uid = www-data
gid = www-data

buffer-size = 32768
enable-threads = true
single-interpreter = true
processes = 1

stats = 127.0.0.1:1717

(NB: 上面的文件名是根据它们相对于 Docker 文件的位置给出的,然后将它们复制到正确的位置,基本上删除前缀 files)

目前我使用的 uWSGI Docker 图像是基于 ubuntu:trusty 基础图像构建的(虽然我已经尝试过 ubuntu:latestalpine:latest 并且遇到了同样的问题),虽然我试图用主管启动 uWSGI 进程,如前所述,当直接从命令行 运行 时它也会失败。在 Docker 图像中,我使用 pip 安装 uWSGI,但也尝试使用 apt-get 得到相同的结果。

我还应该提到我已经尝试了不同版本的 uWSGI 2.0.13.1 和 1。9.something 如果有帮助的话,结果相同。

# Dockerfile
FROM ubuntu:trusty
MAINTAINER Sean Quinn "me@mail.com"

RUN apt-get update \
 && apt-get install -y \
      ack-grep git nano \
      supervisor \
      build-essential gcc python python-dev python-pip

RUN sed -i 's/^\(\[supervisord\]\)$/\nnodaemon=true/' /etc/supervisor/supervisord.conf \
 && sed -i 's/^\(\[supervisord\]\)$/\nloglevel=debug/' /etc/supervisor/supervisord.conf \
 && sed -i 's/^\(files = .*\)$/;/' /etc/supervisor/supervisord.conf \
 && sed -i 's/^\(\[include\]\)$/\nfiles = \/etc\/supervisor\/conf.d\/*.conf/' /etc/supervisor/supervisord.conf

ENV UWSGI_VERSION 2.0.13.1

RUN pip install uwsgi==${UWSGI_VERSION}

RUN mkdir -p /etc/uwsgi \
 && mkdir -p /etc/uwsgi/apps-available \
 && mkdir -p /etc/uwsgi/apps-enabled \
 && mkdir -p /var/log/uwsgi

COPY files/etc/supervisor/conf.d/uwsgi.conf /etc/supervisor/conf.d/uwsgi.conf
COPY files/etc/uwsgi/emperor.ini /etc/uwsgi/emperor.ini

VOLUME /etc/uwsgi/apps-enabled
VOLUME /var/www

ENTRYPOINT ["/usr/bin/supervisord"]
CMD ["-c", "/etc/supervisor/supervisord.conf"]

如前所述,supervisord 进程尝试使用以下主管配置启动 uWSGI 进程。

# files/etc/supervisor/conf.d/uwsgi.conf
[program:uwsgi]
command=/usr/local/bin/uwsgi --ini /etc/uwsgi/emperor.ini
user=root

应用程序 Python 文件安装在 /var/www 的子目录中,应用程序 uWSGI 配置安装到 /etc/uwsgi/apps-enabled.

奇怪的是,如果我在一个新的 Ubuntu VM(Docker 之外)上安装 supervisor 和 uWSGI,并且所有配置和文件都已就位,我可以看到 uWSGI 正确处理emperor.ini 并阅读 vassal .ini 文件。我还没有尝试将 nginx 添加到等式中,因为我想首先确保 uWSGI 正在启动并正确读取配置文件。

有什么方法可以增加日志记录或确定为什么我只看到似乎是 uWSGI 二进制文件的版本号?这就像 uWSGI 进程完全忽略了命令行选项。我觉得我错过了一些显而易见的东西。

提前感谢任何人可以提供的帮助!

tl;dr don't use UWSGI_VERSION as an environment variable, apparently it forces uWSGI to only print the version number instead of start?

我相信我解决了我自己的问题!

在 Docker 的集线器上试验其他 uWSGI 图像后,我发现它们也 运行 陷入同样的​​问题,所以我开始进一步研究可能的配置问题。我尝试更改权限等。

然而我注意到当我使用jpetazzo/nsenter进入我看到uWSGI启动的运行容器时(而不是像上面突出显示的那样简单地输出uWSGI版本信息)。使用docker exec输入时,uWSGI只会打印版本信息。玩了一会儿之后,我发现从使用 docker exec 启动的容器中发出命令 su - 我再次看到 uWSGI 启动。

经过一些检查,我发现 root 用户在一个 shell 与另一个用户之间的环境变量存在一些差异。它引导我找到 UWSGI_VERSION 环境变量,这似乎是罪魁祸首,因为删除 UWSGI_VERSION 允许 uWSGI 启动。

我修改了我的 Docker 文件以使用 UWSGI_PIP_VERSION 作为环境变量来指示要安装的 uWSGI 版本,这似乎是 UWSGI_VERSION 的安全替代方案。 YMMV.