Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to connect to Redis returns an ECONNREFUSED

I have the following 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"

And I'm using the following env variables to connect to Mongo and Redis

REDIS_URL=redis://redis:6379
DATABASE_URL=mongodb://mongo:27017/webapp

With this configuration, when the app starts it can connect to the Mongo container, but it fails to connect to Redis with the following error:

Error: connect ECONNREFUSED 127.0.0.1:6379

I tried exposing and mapping the ports:

    expose:
      - "6379"
    ports:
      - "6379:6379"

but it still doesn't solve the issue. Mapping the ports I can use redis-cli to connect to Redis, so I know the container is running.

Any clues?

EDIT: Running the webapp on my machine without Docker works normally. I tried both, native Redis and Mongo as well as running with the docker-compose below commenting out the web section and mapping the ports.

EDIT 2: Output of 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)

EDIT 3: Adding where the app connects to 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}`,
            );
        }
    },
});

The log output:

-------------- 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 }
like image 507
JayC Avatar asked Jun 05 '18 11:06

JayC


1 Answers

The configuration you described is not being used by your application:

REDIS_URL=redis://redis:6379

When you see the connection run, it's trying to connect to 127.0.0.1 instead of the container ip:

Error: connect ECONNREFUSED 127.0.0.1:6379

To solve this, you'll need to reconfigure your app so that it uses the redis DNS name instead of 127.0.0.1. Each container has its own private loopback interface, so connecting to this inside a container will connect to the container itself, not your host or any other container running on the host.

As an aside, do not use links. They have been deprecated. The built in DNS will give name resolution to the service name. If you have dependencies between containers, it's best to handle this in the application or entrypoint. You can also use depends_on to list service dependencies, but this only works with docker-compose, and does not verify the health of the dependent services.

like image 200
BMitch Avatar answered Sep 20 '22 02:09

BMitch