You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

容器化Flask+Celery+Redis应用启动Celery Worker时遇Redis属性错误

容器化Flask+Celery应用启动Worker失败解决方案

问题背景

尝试以容器化方式运行集成Celery的Flask应用执行后台任务,基于mambaorg/micromamba:latest镜像构建,多次调整配置后Celery Worker始终无法启动。

环境配置

依赖清单(environment.yml)

name: base
channels:
  - conda-forge
  - anaconda
dependencies:
  - python=3.10.6
  - mne=1.1.1
  - mne-features=0.2.1
  - ray-default
  - flask
  - celery
  - redis

Docker Compose配置

version: '2.4'

services:
  redis-service:
    image: redis:latest
    container_name: redis-service

  celery-service:
    image: myapp:1.0.0
    container_name: celery-service
    environment:
      - FLASK_APP=run
    volumes:
      - .:/app/
    depends_on:
      - redis-service
    command: celery -A run.celery worker --loglevel=info

  genfeatsbs:
    image: myapp:1.0.0
    container_name: myapp
    environment:
      - FLASK_APP=run
      - FLASK_DEBUG=1
    volumes:
      - .:/app/ # 包含源码和启动脚本run.py
    ports:
      - '5000:5000'
    depends_on:
      - redis-service
    command: flask run -h 0.0.0.0

Flask应用初始化(init.py)

from celery import Celery, Task
from flask import Flask

from app.routes.execution_blueprint import execution_blueprint

def make_celery(app: Flask) -> Celery:
    class FlaskTask(Task):
        def __call__(self, *args: object, **kwargs: object) -> object:
            with app.app_context():
                return self.run(*args, **kwargs)
        
    celery = Celery(app.name)
    celery.conf.update(app.config["CELERY"])
    celery.Task = FlaskTask
    
    return celery

def create_app(config_file) -> Flask:
    app = Flask(__name__)
    app.config.from_object(config_file)
    
    celery = make_celery(app)
    celery.set_default()
    
    app.register_blueprint(execution_blueprint)
    
    return app, celery

Celery配置

CELERY = {
    'broker_url': 'redis://redis-service',
    'result_backend': 'redis://redis-service'
}

启动脚本(run.py)

from myapp import create_app

app, celery = create_app('app.config.Config')
app.app_context().push()

报错信息

Traceback (most recent call last):
  File "/opt/conda/bin/celery", line 10, in <module>
    sys.exit(main())
  File "/opt/conda/lib/python3.10/site-packages/celery/__main__.py", line 15, in main
    sys.exit(_main())
  File "/opt/conda/lib/python3.10/site-packages/celery/bin/celery.py", line 235, in main
    return celery(auto_envvar_prefix="CELERY")
  File "/opt/conda/lib/python3.10/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/opt/conda/lib/python3.10/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/opt/conda/lib/python3.10/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/opt/conda/lib/python3.10/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/opt/conda/lib/python3.10/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/opt/conda/lib/python3.10/site-packages/click/decorators.py", line 33, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/opt/conda/lib/python3.10/site-packages/celery/bin/base.py", line 134, in caller
    return f(ctx, *args, **kwargs)
  File "/opt/conda/lib/python3.10/site-packages/celery/bin/worker.py", line 348, in worker
    worker = app.Worker(
  File "/opt/conda/lib/python3.10/site-packages/celery/worker/worker.py", line 98, in __init__
    self.setup_instance(**self.prepare_args(**kwargs))
  File "/opt/conda/lib/python3.10/site-packages/celery/worker/worker.py", line 119, in setup_instance
    self._conninfo = self.app.connection_for_read()
  File "/opt/conda/lib/python3.10/site-packages/celery/app/base.py", line 818, in connection_for_read
    return self._connection(url or self.conf.broker_read_url, **kwargs)
  File "/opt/conda/lib/python3.10/site-packages/celery/app/base.py", line 877, in _connection
    return self.amqp.Connection(
  File "/opt/conda/lib/python3.10/site-packages/kombu/connection.py", line 201, in __init__
    if not get_transport_cls(transport).can_parse_url:
  File "/opt/conda/lib/python3.10/site-packages/kombu/transport/__init__.py", line 90, in get_transport_cls
    _transport_cache[transport] = resolve_transport(transport)
  File "/opt/conda/lib/python3.10/site-packages/kombu/transport/__init__.py", line 75, in resolve_transport
    return symbol_by_name(transport)
  File "/opt/conda/lib/python3.10/site-packages/kombu/utils/imports.py", line 59, in symbol_by_name
    module = imp(module_name, package=package, **kwargs)
  File "/opt/conda/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/opt/conda/lib/python3.10/site-packages/kombu/transport/redis.py", line 266, in <module>
    class PrefixedStrictRedis(GlobalKeyPrefixMixin, redis.Redis):
AttributeError: 'NoneType' object has no attribute 'Redis'

问题根源

报错核心是AttributeError: 'NoneType' object has no attribute 'Redis',说明Kombu(Celery依赖的消息库)尝试导入redis.Redis时,redis模块为None。原因是:

  • Conda仓库中的redis包是Redis服务器二进制文件,并非Python连接Redis所需的客户端库。Celery需要的Python客户端库在Conda中名为redis-py,或通过pip安装redis包。

解决方案

1. 修正依赖清单

将environment.yml中的redis替换为redis-py,确保安装的是Python Redis客户端:

name: base
channels:
  - conda-forge
  - anaconda
dependencies:
  - python=3.10.6
  - mne=1.1.1
  - mne-features=0.2.1
  - ray-default
  - flask
  - celery
  - redis-py  # 替换原有的redis

或者改用pip安装客户端(如果Conda源存在版本兼容问题):

name: base
channels:
  - conda-forge
  - anaconda
dependencies:
  - python=3.10.6
  - mne=1.1.1
  - mne-features=0.2.1
  - ray-default
  - flask
  - celery
  - pip:
    - redis  # 通过pip安装Python Redis客户端

2. 添加Redis服务健康检查

Docker Compose的depends_on仅保证启动顺序,不确保Redis服务就绪。为redis-service添加健康检查,确保Celery Worker在Redis完全启动后再启动:

redis-service:
  image: redis:latest
  container_name: redis-service
  healthcheck:
    test: ["CMD", "redis-cli", "ping"]
    interval: 5s
    timeout: 3s
    retries: 5

celery-service:
  # ... 其他配置不变
  depends_on:
    redis-service:
      condition: service_healthy

3. 明确Celery Redis连接配置

在Celery配置中明确端口和数据库索引,避免默认值可能的歧义:

CELERY = {
    'broker_url': 'redis://redis-service:6379/0',
    'result_backend': 'redis://redis-service:6379/0'
}

4. 重新构建镜像并启动服务

执行以下命令重新构建应用镜像并启动所有服务:

docker-compose build
docker-compose up -d

验证

启动后查看Celery Worker日志:

docker logs celery-service

如果看到类似[INFO] Connected to redis://redis-service:6379/0的日志,说明Worker已成功连接Redis并启动。

内容的提问来源于stack exchange,提问作者Armando Canales Lima

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 09:04:51