Docker环境下指定正确主机名后Celery仍无法连接Redis
Docker环境中Celery无法连接Redis问题排查
问题概述
在Docker环境中,已指定Redis主机名为redis,Redis服务已正常启动,但Celery容器始终无法连接Redis,报错连接超时。
相关配置文件
Dockerfile
FROM python:3.8.16-bullseye RUN apt-get install ca-certificates RUN update-ca-certificates COPY requirements.txt requirements.txt RUN pip install --upgrade pip && pip install -r requirements.txt COPY . . WORKDIR /task_manager CMD celery -A worker.celery worker --loglevel info --uid nobody
worker.py代码
from celery import Celery import os BROKER_URI = os.environ["BROKER_URI"] BACKEND_URI = os.environ["BACKEND_URI"] celery = Celery('worker', backend=BACKEND_URI) celery.conf.broker_url = BROKER_URI
docker-compose配置
version: "3.8" services: worker: container_name: celery environment: - BROKER_URI=redis://redis - BACKEND_URI=redis://redis build: context: . dockerfile: Dockerfile depends_on: - redis redis: image: "redis:alpine" ports: - 6379:6379
错误日志
celery | celery | -------------- celery@f760551b7908 v5.2.7 (dawn-chorus) celery | --- ***** ----- celery | -- ******* ---- Linux-5.19.0-41-generic-x86_64-with-glibc2.2.5 2023-05-05 15:05:25 celery | - *** --- * --- celery | - ** ---------- [config] celery | - ** ---------- .> app: worker:0x7f223ace3a00 celery | - ** ---------- .> transport: redis://redis:6379/0 celery | - ** ---------- .> results: redis://redis:6379/0 celery | - *** --- * --- .> concurrency: 8 (prefork) celery | -- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker) celery | --- ***** ----- celery | -------------- [queues] celery | .> celery exchange=celery(direct) key=celery celery | celery | celery | [tasks] celery | celery | celery | [2023-05-05 15:07:35,918: ERROR/MainProcess] consumer: Cannot connect to redis://redis:6379/0: Error 110 connecting to redis:6379. Connection timed out.. celery | Trying again in 2.00 seconds... (1/100)
排查与解决方案
1. 解决depends_on的启动顺序局限性
depends_on仅保证容器启动顺序,不确保Redis服务完全初始化完成。Celery启动时Redis可能还未就绪,导致连接超时。
方案1:使用wait-for-it工具等待Redis端口
修改Dockerfile,添加工具安装和启动命令:
FROM python:3.8.16-bullseye RUN apt-get update && apt-get install -y ca-certificates wait-for-it RUN update-ca-certificates COPY requirements.txt requirements.txt RUN pip install --upgrade pip && pip install -r requirements.txt COPY . . WORKDIR /task_manager CMD wait-for-it redis:6379 -- celery -A worker.celery worker --loglevel info --uid nobody
方案2:用Shell循环检测Redis端口(无需额外工具)
修改Dockerfile,安装netcat并添加等待逻辑:
FROM python:3.8.16-bullseye RUN apt-get update && apt-get install -y ca-certificates netcat RUN update-ca-certificates COPY requirements.txt requirements.txt RUN pip install --upgrade pip && pip install -r requirements.txt COPY . . WORKDIR /task_manager CMD until nc -z redis 6379; do sleep 1; done && celery -A worker.celery worker --loglevel info --uid nobody
2. 检查Redis网络绑定配置
若Redis容器绑定了127.0.0.1,则仅允许本地访问,其他容器无法连接。修改docker-compose的Redis服务,显式指定绑定所有IP:
redis: image: "redis:alpine" ports: - 6379:6379 command: redis-server --bind 0.0.0.0
3. 验证容器网络连通性
进入Celery容器,测试与Redis的连通性:
docker exec celery ping redis # 或测试端口 docker exec celery nc -zv redis 6379
如果ping不通,说明网络配置异常,检查docker-compose是否使用默认网络,或是否自定义了网络但未将两个服务加入同一网络。
4. 显式指定Redis连接参数
将环境变量中的URI改为完整格式,避免默认参数歧义:
worker: environment: - BROKER_URI=redis://redis:6379/0 - BACKEND_URI=redis://redis:6379/0
内容的提问来源于stack exchange,提问作者Bob
相关产品推荐
相关产品推荐

