在同一个容器中运行 celery worker + beat
Posted
技术标签:
【中文标题】在同一个容器中运行 celery worker + beat【英文标题】:Running celery worker + beat in the same container 【发布时间】:2018-09-16 12:04:23 【问题描述】:我的烧瓶应用由四个容器组成:web 应用、postgres、rabbitMQ 和 Celery。由于我有定期运行的 celery 任务,因此我使用的是 celery beat。我已经像这样配置了我的 docker-compose 文件:
version: '2'
services:
rabbit:
# ...
web:
# ...
rabbit:
# ...
celery:
build:
context: .
dockerfile: Dockerfile.celery
我的 Dockerfile.celery 看起来像这样:
# ...code up here...
CMD ["celery", "-A", "app.tasks.celery", "worker", "-B", "-l", "INFO"]
虽然我在文档中读到我不应该使用 -B
选项进入生产环境,但我还是匆匆添加了它(并忘记了更改它)并很快了解到我的计划任务正在运行多次。对于那些感兴趣的人,如果您在 celery 容器中执行ps aux | grep celery
,您将看到多个 celery + beat 进程正在运行(但应该只有一个 beat 进程和许多工作进程)。我从文档中不确定为什么不应该在生产环境中运行 -B
,但现在我知道了。
然后我将 Dockerfile.celery 更改为:
# ...code up here...
CMD ["celery", "-A", "app.tasks.celery", "worker", "-l", "INFO"]
CMD ["celery", "-A", "app.tasks.celery", "beat", "-l", "INFO"]
不,当我启动我的应用程序时,工作进程会启动,但 beat 不会。当我翻转这些命令以便首先调用 beat 时,beat 会启动,但工作进程不会。所以我的问题是:如何在容器中同时运行 celery worker + beat?我已经梳理了许多文章/文档,但我仍然无法弄清楚这一点。
已编辑
我将 Dockerfile.celery 更改为以下内容:
ENTRYPOINT [ "/bin/sh" ]
CMD [ "./docker.celery.sh" ]
我的 docker.celery.sh 文件如下所示:
#!/bin/sh -ex
celery -A app.tasks.celery beat -l debug &
celery -A app.tasks.celery worker -l info &
但是,我收到了错误celery_1 exited with code 0
编辑#2
我在 docker.celery.sh 文件的末尾添加了以下阻塞命令,一切都已修复:
tail -f /dev/null
【问题讨论】:
您可以为节拍创建另一个容器并覆盖其工作命令...当您扩展您的工作人员时,您将只扩展他们而不是节拍(调度程序) @MazelTov - 很好的建议,对于我的下一个项目,我会考虑将它们放在单独的容器中。由于各种原因,我需要这两个进程在同一个容器中运行。 【参考方案1】:docker 只运行一个 CMD,所以只有第一个 CMD 被执行,解决方法是创建一个 bash 脚本来执行 worker 和 beat,并使用 docker CMD 来执行这个脚本
【讨论】:
感谢您的回答,但不幸的是,它对我不起作用。使用您的建议,我遇到了同样的问题:也就是说,在我的 Dockerfile.celery 中,我正在运行 ENTRYPOINT [“/bin/sh”],然后是 CMD [“./docker.celery.sh”]。 shell 脚本有两个命令:celery -A app.tasks.celery beat -l debug
后跟celery -A app.tasks.celery worker -l info
。和以前一样,第一个命令执行但第二个不执行。我做错了吗?
第一行是否以&
结尾意味着在后台执行并继续到下一行(第二行也应以&
结尾以最佳实践使用)
我已将 & 添加到每个命令的末尾,但在启动容器时,我收到以下错误 celery_1 exited with code 0
。我已将我的 shell 脚本添加到我的原始帖子中。还有其他建议吗?
似乎容器正在运行所有服务并且不存在,请尝试在 bash 脚本末尾添加一个阻塞 cmd,例如 tailf
某些文件或其他内容
仅供参考:我修复了使用 tail -f /dev/null
时遇到的最后一个错误。【参考方案2】:
您可以使用celery beatX 进行节拍。允许(并建议)拥有多个 beatX 实例。他们使用锁来同步。
不能说它是否可以生产,但它对我来说就像一个魅力(使用-B
键)
【讨论】:
Celery beatX 看起来很有趣。但是,它目前似乎只适用于 Redis 和 Memcached。我正在使用 RabbitMQ,并且不希望在我的堆栈中添加更多技术。但很高兴知道这一点,所以感谢您的建议。【参考方案3】:如上所述,我是通过输入入口点得到的,另外我添加了 &> 以将输出保存在日志文件中。
我的入口点.sh
#!/bin/bash
python3 manage.py migrate
python3 manage.py migrate catalog --database=catalog
python manage.py collectstatic --clear --noinput --verbosity 0
# Start Celery Workers
celery worker --workdir /app --app dri -l info &> /log/celery.log &
# Start Celery Beat
celery worker --workdir /app --app dri -l info --beat &> /log/celery_beat.log &
python3 manage.py runserver 0.0.0.0:8000
【讨论】:
以上是关于在同一个容器中运行 celery worker + beat的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Django 1.11 中运行 celery worker
如何在 AWS Elastic Beanstalk 上运行 celery worker?