【问题标题】:why would you separate a celery worker and django container?你为什么要把芹菜工人和 django 容器分开?
【发布时间】:2023-01-26 20:52:24
【问题描述】:

我正在用芹菜构建一个 django 应用程序。我尝试为工人编写一个没有容器的 docker-compose。在我的 django Dockerfile 中,一个运行 celery worker 和 django 应用程序的入口点:

...
python manage.py migrate
celery -A api worker -l INFO --detach
python manage.py runserver 0.0.0.0:8000

芹菜将使用此命令运行,但不会使用 django runserver。我在教程中看到他们将 django 容器与 woker 容器分开,反之亦然。我看不出对这种分离的解释。我还观察到两个 python 容器(django、worker)具有相同的体积。如果 celery 与 django 具有不同的环境,它如何添加任务?在我看来,两个容器将有两个 django 应用程序(相同的体积),其中一个运行 runserver,另一个运行 celery worker。我不明白分离。

【问题讨论】:

    标签: django docker celery


    【解决方案1】:

    正如 Celery documentation 提到的:

    Celery 通过消息进行通信,通常使用 broker 来调解 客户和工人之间。为了启动一个任务,客户端添加了一个 消息到队列,代理然后将该消息传递给 工人。

    这意味着客户端 (Django) 和工作者 (Celery) 之间的通信是通过消息队列完成的。因此,工人和客户是否在不同的容器甚至不同的机器中都没有关系。如果 Client 可以访问消息队列(例如使用 Redis 或 RabbitMQ)并且 worker 可以从该队列中弹出任务,那么它将始终有效。如果您使用两个容器,那么它们需要共享卷,因为源代码和执行任务所需的任何其他数据。

    关于 docker-compose 部分,没有理想的标准来保留或分离 Celery 和 Django。您可以将它们放在同一个容器中,也可以不放在同一个容器中,这取决于您和项目的要求。

    【讨论】:

    • 谢谢@ruddra,在为两个维护一个容器时,您将如何运行 celery 或 django runserver,反之亦然?
    • 我不明白为什么这两个容器(如果有的话)会有相同的体积。
    • .如果您使用两个容器,那么它们需要共享卷,因为源代码和执行任务所需的任何其他数据。
    【解决方案2】:

    您应该将容器设置为在每个容器中仅运行一个前台进程,而不运行后台进程。即使在这个简单的示例中,也有两个明显的优势:如果 Celery worker 发生故障,您可以重新启动一个独立的容器,但它作为后台进程对 Docker 是不可见的;您可以分别读取Web服务器和后台工作人员的docker logs,而不会将它们交织在一起。在更大的规模上,您可以想象想要根据您的负载运行不同数量的 Django 和 Celery 容器。

    为了使这项工作正常进行,入口点脚本不直接运行程序很重要。它通过(可能被覆盖的)容器命令作为参数传递,您可以使用特殊的 shell 构造来运行它

    #!/bin/sh
    ./manage.py migrate
    exec "$@"
    

    在 Dockerfile 中,声明 ENTRYPOINT 和默认的 CMD 以运行 Web 服务器

    ENTRYPOINT ["./entrypoint.sh"]  # probably unchanged, must be JSON array syntax
    CMD ["./manage.py", "runserver", "0.0.0.0:8000"]
    

    在 Compose 设置中,您可以从同一个图像运行多个容器,但为 Celery worker 覆盖 command:

    version: '3.8'
    services:
      web:
        build: .
        ports: ['8000:8000']
        environment:
          REDIS_HOST: redis
      worker:
        build: .
        command: celery -A api worker -l INFO
        environment:
          REDIS_HOST: redis
      redis:
        image: redis
    

    主应用程序通过 Redis(或其他商店)中的队列与 worker 通信,因此它们不需要在同一个容器中。

    【讨论】:

      猜你喜欢
      • 2014-01-06
      • 2023-04-08
      • 2016-02-04
      • 1970-01-01
      • 2018-12-25
      • 2014-08-17
      • 2014-11-24
      • 2015-04-09
      • 1970-01-01
      相关资源
      最近更新 更多