因此,通过 uWSGI 尝试使用 Docker + Supervisord + Django 应用程序。我的整个堆栈工作正常,但需要整理日志记录。
如果我在非守护进程模式下启动supervisor,
/usr/bin/supervisord -n
然后我将主管的日志输出输入到 docker 日志标准输出中。然而,如果supervisord处于守护进程模式,它自己的日志会被隐藏在容器文件系统中,并且其应用程序的日志也会被隐藏在它们自己的app__stderr/stdout文件中。
我想要的是将主管和应用程序 stdout 都记录到 docker 日志中。
以非守护进程模式启动supervisord是一个明智的想法,还是会导致意想不到的后果?另外,如何将应用程序日志也播放到 docker 日志中?
我使用 .
在 Docker 镜像中安装 supervisor-stdout:
RUN apt-get install -y python-pip && pip install supervisor-stdout
编辑你的
supervisord.conf
,如下所示:
[program:myprogram]
command=/what/ever/command
stdout_events_enabled=true
stderr_events_enabled=true
[eventlistener:stdout]
command = supervisor_stdout
buffer_size = 100
events = PROCESS_LOG
result_handler = supervisor_stdout:event_handler
Docker 容器就像一张纸巾,你用了它,然后就扔掉了它。为了“活着”,Docker 需要在前台运行一些东西(而守护进程在后台运行),这就是您使用 Supervisord 的原因。
因此,您需要将进程输出(访问和错误)“重定向/添加/合并”到运行容器时看到的 Supervisord 输出。
正如 Drew 所说,每个人都在使用 https://github.com/coderanger/supervisor-stdout 来实现它(对我来说,这应该添加到supervisord项目中!)。德鲁忘了说的话,你可能需要补充
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
到supervisord程序配置块。
还有一些非常有用的东西,想象一下你的进程正在登录日志文件而不是标准输出,你可以要求supervisord来观看它:
[program:php-fpm-log]
command=tail -f /var/log/php5-fpm.log
stdout_events_enabled=true
stderr_events_enabled=true
这会将 php5-fpm.log 内容重定向到 stdout,然后通过supervisord-stdout重定向到supervisord stdout。
supervisor-stdout 需要安装 python-pip,它下载约 150mb,对于一个容器来说,我认为仅用于安装另一个工具就足够了。
将日志文件重定向到 /dev/stdout 对我有用:
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
http://veithen.github.io/2015/01/08/supervisord-redirecting-stdout.html
我同意,不使用守护进程模式听起来是最好的解决方案,但我可能会采用与您拥有实际物理服务器或某种虚拟机设置时使用的策略相同的策略:集中日志记录。
您可以在容器内使用像 logstash 这样的自托管工具来收集日志并将其发送到中央服务器。或者使用 loggly 或 papertrail 等商业服务来执行相同的操作。
今天的最佳实践是拥有最少的 Docker 镜像。对我来说,带有 Python 应用程序的理想容器只包含我的代码、支持库以及
uwsgi
(如果有必要)之类的东西。
我在 https://github.com/msgre/uwsgi_logging 上发布了一种解决方案。这是
uwsgi
背后的简单 Django 应用程序,配置为在容器 stdout 上显示来自 uwsgi
和 Django 应用程序的日志,而不需要 supervisor
。
我的 python 应用程序(Flask)也遇到了同样的问题。对我有用的解决方案是:
supervisord -n
) 将日志重定向到
/proc/1/fd/1
而不是 /dev/stdout
在我的docker镜像中设置这两个环境变量
PYTHONUNBUFFERED=True
和PYTHONIOENCODING=UTF-8
只需将以下行添加到您各自的supervisor.ini 配置文件中即可。
redirect_stderr=true
stdout_logfile=/proc/1/fd/1
将这些变量导出到应用程序(linux)环境。
$ export PYTHONUNBUFFERED=True
$ export PYTHONIOENCODING=UTF-8
确实,以非守护进程模式启动supervisord是最好的解决方案。
您还可以使用卷将主管的日志安装到中央位置。
只是为后代留下一个工作样本:
supervisord.conf 文件
[supervisord]
nodaemon=true
user=root
[program:crond]
command=crond -f -L /dev/stdout
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile_maxbytes=0
[program:django]
command=python3 manage.py runserver 0.0.0.0:8000
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile_maxbytes=0
Dockerfile [程序:django]
FROM python:3.11-alpine
WORKDIR /app
COPY requirements.txt /app
RUN pip3 install -r requirements.txt --no-cache-dir
# Install make
RUN apk update && apk add make nano curl wget supervisor
RUN mkdir -p /var/log/supervisor
# Copy supervisord configuration file
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY . /app
COPY ./Makefile-linux Makefile
RUN chmod 777 celery-entrypoint.sh
RUN chmod 777 manage.py
RUN rm /app/Makefile-linux
RUN python3 manage.py crontab add
ENTRYPOINT ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
CMD ["-n"]