尝试连接到 Redis 返回 ECONNREFUSED

Jay*_*ayC 4 docker docker-compose

我有以下几点docker-compose.yml

version: '3'
services:
  web:
    build: .
    image: webapp
    env_file: .env.docker
    ports:
      - "3000:3000"
    links:
      - redis
      - mongo
  redis:
    image: "redis:alpine"
  mongo:
    image: "mongo"
Run Code Online (Sandbox Code Playgroud)

我使用以下环境变量连接到 Mongo 和 Redis

REDIS_URL=redis://redis:6379
DATABASE_URL=mongodb://mongo:27017/webapp
Run Code Online (Sandbox Code Playgroud)

使用此配置,当应用程序启动时,它可以连接到 Mongo 容器,但无法连接到 Redis,并出现以下错误:

Error: connect ECONNREFUSED 127.0.0.1:6379
Run Code Online (Sandbox Code Playgroud)

我尝试公开和映射端口:

    expose:
      - "6379"
    ports:
      - "6379:6379"
Run Code Online (Sandbox Code Playgroud)

但它仍然没有解决问题。映射端口 我可以使用 redis-cli 连接到 Redis,所以我知道容器正在运行。

有什么线索吗?

编辑:在没有 Docker 的情况下在我的机器上运行 webapp 正常工作。我尝试了本机 Redis 和 Mongo 以及运行docker-compose下面的注释web部分并映射端口。

编辑 2:输出 lsof

COMMAND    PID    USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
com.docke 3136 JayC   20u  IPv4 0x7dac4a08aadc94c9      0t0  TCP *:6379 (LISTEN)
com.docke 3136 JayC   21u  IPv6 0x7dac4a08bbf50781      0t0  TCP localhost:6379 (LISTEN)
Run Code Online (Sandbox Code Playgroud)

编辑 3:添加应用程序连接到 Redis 的位置:

const { RedisPubSub } = require('graphql-redis-subscriptions');

console.log(`-------------- REDIS_URL: ${process.env.REDIS_URL} --------------`);

const engine = new RedisPubSub({
    connection: {
        url: process.env.REDIS_URL,
    },
    connectionListener: err => {
        if (err) {
            Logger.sys.error(
                `redis connection failed at ${process.env.REDIS_URL}`,
            );
            Logger.sys.error(err);
        } else {
            Logger.sys.info(
                `pubsub connected to redis at ${process.env.REDIS_URL}`,
            );
        }
    },
});
Run Code Online (Sandbox Code Playgroud)

日志输出:

-------------- REDIS_URL: redis://redis:6379 --------------
2018-06-05T13:21:37.658Z - error: redis connection failed at redis://redis:6379
2018-06-05T13:21:37.659Z - error: { Error: connect ECONNREFUSED 127.0.0.1:6379
    at Object._errnoException (util.js:1022:11)
    at _exceptionWithHostPort (util.js:1044:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1182:14)
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 6379 }
Run Code Online (Sandbox Code Playgroud)

BMi*_*tch 7

您的应用程序未使用您描述的配置:

REDIS_URL=redis://redis:6379
Run Code Online (Sandbox Code Playgroud)

当您看到连接运行时,它正在尝试连接到 127.0.0.1 而不是容器 ip:

Error: connect ECONNREFUSED 127.0.0.1:6379
Run Code Online (Sandbox Code Playgroud)

要解决此问题,您需要重新配置您的应用,使其使用 redis DNS 名称而不是 127.0.0.1。每个容器都有自己的私有环回接口,因此在容器内连接到此接口将连接到容器本身,而不是您的主机或主机上运行的任何其他容器。

顺便说一句,不要使用链接。它们已被弃用。内置的 DNS 将为服务名称提供名称解析。如果容器之间存在依赖关系,最好在应用程序或入口点中处理此问题。您还可以使用depends_on列出服务依赖项,但这仅适用于 docker-compose,并且不会验证依赖服务的健康状况。

  • 感谢您的答复!我终于明白为什么它不起作用了。我将电话添加到我的问题中,因此答案很明确。传递给 RedisPubSub 构造函数的“connection”属性是错误的,它默认为“redis://localhost:6379”,它在本地工作,但在 Docker 上不起作用。 (2认同)