芹菜工人无法连接到 docker 实例上的 redis

Posted

技术标签:

【中文标题】芹菜工人无法连接到 docker 实例上的 redis【英文标题】:Celery workers unable to connect to redis on docker instances 【发布时间】:2018-04-26 14:12:55 【问题描述】:

我有一个运行 Django 应用程序的 dockerized 设置,我在其中使用 Celery 任务。 Celery 使用 Redis 作为代理。

版本控制:

Docker 版本 17.09.0-ce,构建 afdb6d4 docker-compose 版本 1.15.0,构建 e12f3b9 Django==1.9.6 django-celery-beat==1.0.1 celery==4.1.0 芹菜[redis] redis==2.10.5

问题:

我的 celery worker 似乎无法连接到位于 localhost:6379 的 redis 容器。我能够在指定端口上远程登录到 redis 服务器。我能够验证 redis-server 是否在容器上运行。

当我手动连接到 Celery docker 实例并尝试使用命令 celery -A backend worker -l info 创建一个工作器时,我收到了通知:

[2017-11-13 18:07:50,937: ERROR/MainProcess] consumer: Cannot connect to redis://localhost:6379/0: Error 99 connecting to localhost:6379. Cannot assign requested address.. Trying again in 4.00 seconds...

注意事项:

我可以通过 6379 端口远程登录到 redis 容器。在 redis 容器上,redis-server 正在运行。

我还有什么遗漏的吗?我已经在兔子洞里走得很远了,但感觉我错过了一些非常简单的东西。

Docker 配置文件:

docker-compose.common.yml here docker-compose.dev.yml here

【问题讨论】:

尝试用127.0.0.1替换localhost 你有 docker-compose 文件吗?分享吧。 @Opal 将配置文件添加到帖子底部。 当我更改为 127.0.0.1 时,@warvariuc 的结果相同。另外需要注意的是,使用 redis 容器的 docker IP 地址也不起作用。 肯定不会是localhost,因为redis不工作不能和celery在同一个主机上工作。你能通过 celery 的 IP ping redis 吗? 【参考方案1】:

当您使用 docker-compose 时,您不会使用 localhost 进行容器间通信,您将使用容器的 compose 分配的主机名。在这种情况下,您的 redis 容器的主机名是 redisservices: 下的***元素是您的默认主机名。

所以要让celery 连接redis,你应该试试redis://redis:6379/0。由于协议和服务名称相同,我将详细说明:如果您在 docker-compose 中将 redis 服务命名为“butter-pecan-redis”,则改为使用redis://butter-pecan-redis:6379/0

另外,docker-compose.dev.yml 似乎没有 celery 和 redis 在一个公共网络上,这可能会导致它们无法看到彼此。我相信他们需要至少共享一个网络才能解析各自的主机名。

Networking in docker-compose 在前几段中有一个示例,还有一个 docker-compose.yml 可供查看。

【讨论】:

他们没有共享一个公共网络,这有助于解决问题。 如果我的两个容器在同一个网络中,这种redis://butter-pecan-redis:6379/0 的连接方式仍然有效吗??(我不想使用 docker-compose) @AATHITHRAJENDRAN 不,不会。 Docker 继承了主机的 DNS,因此除非您将 butter-pecan-redis 的 DNS 条目映射到 Docker 外部某处的 localhost:<port>,否则一个容器不会按名称解析另一个容器。 Docker-compose 做了一些额外的事情来让它工作,我不记得它是否在 compose 中具有每个 Docker 网络的 DNS,或者 docker-compose 是否调整主机或 resolv.conf。无论哪种方式,简单的按名称解析都是 docker-compose 功能。 这是我最终通过 docker-compose.yml 文件让 Docker、Django、Celery 和 Redis 一起工作的难题中缺失的部分。感谢您解释这一点!【参考方案2】:

您可能需要将 link 和 depends_on 部分添加到您的 docker compose 文件中,然后通过它们的主机名引用容器。

更新了 docker-compose.yml:

version: '2.1'
services:
    db:
        image: postgres
    memcached:
        image: memcached
    redis:
        image: redis
        ports:
          - '6379:6379'
    backend-base:
        build:
            context: .
            dockerfile: backend/Dockerfile-base
        image: "/backend:base"
    backend:
        build:
            context: .
            dockerfile: backend/Dockerfile
        image: "/backend:$ENV:-local"
        command: ./wait-for-it.sh db:5432 -- gunicorn backend.wsgi:application -b 0.0.0.0:8000 -k gevent -w 3
        ports:
            - 8000
        links:
            - db
            - redis
            - memcached
        depends_on:
            - db
            - redis
            - memcached
    celery:
        image: "/backend:$ENV:-local"
        command: ./wait-for-it.sh db:5432 -- celery worker -E -B --loglevel=INFO --concurrency=1
        environment:
            C_FORCE_ROOT: "yes"
        links:
            - db
            - redis
            - memcached
        depends_on:
            - db
            - redis
            - memcached
    frontend-base:
        build:
            context: .
            dockerfile: frontend/Dockerfile-base
            args:
                NPM_REGISTRY: http://.view.build
                PACKAGE_INSTALLER: yarn
        image: "/frontend:base"
        links:
            - db
            - redis
            - memcached
        depends_on:
            - db
            - redis
            - memcached
    frontend:
        build:
            context: .
            dockerfile: frontend/Dockerfile
        image: "/frontend:$ENV:-local"
        command: 'bash -c ''gulp'''
        working_dir: /app/user
        environment:
            PORT: 3000
        links:
            - db
            - redis
            - memcached
        depends_on:
            - db
            - redis
            - memcached

然后配置redis、postgres、memcached等的url:

redis://redis:6379/0 postgres://user:pass@db:5432/database

【讨论】:

您好,感谢您的贡献。 “......配置redis,postgres,memcached......的url”到底是什么意思?【参考方案3】:

对我来说,问题是所有容器,包括 celery,都指定了网络参数。如果是这种情况,redis 容器也必须具有相同的参数,否则您将收到此错误。见下文,修复是添加“网络”:

  redis:
    image: redis:alpine
    ports:
      - '6379:6379'
    networks:
      - server

【讨论】:

以上是关于芹菜工人无法连接到 docker 实例上的 redis的主要内容,如果未能解决你的问题,请参考以下文章

芹菜不起作用:无法连接到 amqp://guest:**@127.0.0.1:5672//

无法使用mongoose连接到mongo docker镜像

无法从外部 docker 连接到 dockerized redis 实例

无法从 docker 容器连接到 SQL Server

无法连接到 Mac OS X 上的 Docker 守护程序

无法连接到 Anyconnect *** 上的 docker