如何在Docker容器中结合MySQL、RabbitMQ运行Celery Worker和Beat?
解决Docker中Celery Worker/Beat与MySQL、RabbitMQ协同运行的问题
核心问题梳理
- 缺失RabbitMQ服务:Celery依赖消息队列实现任务分发,但当前Docker Compose未配置RabbitMQ服务
- 网络隔离问题:MySQL容器未加入自定义网络
my_network,导致Celery容器无法解析vineCal_db主机名 - 数据库就绪检测缺失:
depends_on仅保证容器启动顺序,不等待数据库服务完全就绪 - Celery初始化时提前查询数据库:
celery.py模块加载阶段直接执行数据库查询,此时数据库未就绪或无法连接 - Celery应用实例配置不规范:Celery无法找到正确的应用实例入口
具体修复步骤
1. 新增RabbitMQ服务配置
在Docker Compose的services节点中添加RabbitMQ服务:
rabbitmq: image: rabbitmq:3-management ports: - "5672:5672" - "15672:15672" environment: RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-guest} RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-guest} networks: - my_network
同时在.env文件中补充RabbitMQ相关环境变量:
RABBITMQ_USER=guest RABBITMQ_PASSWORD=guest CELERY_BROKER_URL=amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672//
2. 修复MySQL容器网络配置
给vineCal_db服务添加网络配置,加入自定义网络:
vineCal_db: image: mysql:latest environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_USER: ${DB_USERNAME} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_DATABASE: ${DB_NAME} volumes: - data:/var/lib/mysql ports: - "3306:3306" networks: - my_network # 新增该行,加入自定义网络
3. 实现数据库就绪等待机制
第一步:在Dockerfile中安装等待脚本
RUN wget -O /usr/local/bin/wait-for-it https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh \ && chmod +x /usr/local/bin/wait-for-it
第二步:修改Celery服务启动命令
celery_worker: build: . command: > sh -c "wait-for-it vineCal_db:3306 -t 60 && celery -A vinecalc_server worker --loglevel=info" volumes: - .:/app env_file: - .env depends_on: - vineCal_db - rabbitmq networks: - my_network celery_beat: build: . command: > sh -c "wait-for-it vineCal_db:3306 -t 60 && celery -A vinecalc_server beat --loglevel=info" volumes: - .:/app env_file: - .env depends_on: - vineCal_db - rabbitmq networks: - my_network
4. 修复Celery初始化时的数据库查询问题
修改/app/vinecalc_server/celery.py,将模块加载阶段的数据库查询改为延迟加载:
# 原错误代码(模块加载时直接查询) tenant_queues = [tenant.queue_name for tenant in Tenant.objects.all()] # 修改为延迟加载函数 def get_tenant_queues(): from .models import Tenant return [tenant.queue_name for tenant in Tenant.objects.all()]
在需要使用队列列表的业务逻辑中调用get_tenant_queues()函数,而非直接使用全局变量。
5. 规范Celery应用实例配置
确保vinecalc_server/celery.py正确导出Celery实例:
import os from celery import Celery os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'vinecalc_server.settings') app = Celery('vinecalc_server') app.config_from_object('django.conf:settings', namespace='CELERY') app.autodiscover_tasks()
同时在vinecalc_server/__init__.py中添加:
from .celery import app as celery_app __all__ = ('celery_app',)
6. 更新Web服务依赖
给web服务添加RabbitMQ依赖,确保服务启动顺序合理:
web: build: . command: gunicorn --bind 0.0.0.0:8000 --workers 3 vinecalc_server.wsgi:application volumes: - .:/app env_file: - .env ports: - "8000:8000" depends_on: - vineCal_db - rabbitmq # 新增该行 networks: - my_network
验证运行
执行以下命令重新构建并启动服务:
docker-compose up --build
内容的提问来源于stack exchange,提问作者Tanveer
相关产品推荐
相关产品推荐

