Create a Redis cluster with docker for NodeJs application with ioredis

343 Views Asked by At

I need to find a way to easily create a development environment on a local machine no matter what operating system it runs, it must be compatible with x86 and arm64 systems.

This environment needs a redis cluster.

So I managed to create a redis cluster with docker.

It just consists to create 6 redis container, each container in a docker network.

When the 6 redis are up and running, I connect to the first container dans do stuff to create the cluster, at this step everything works and is ok.

The problem is that the nodeJs applications that I use, uses old version of a dependency called ioredis.

If I give to the application the ip address of my redis-1 container so for example 127.0.0.1:7001 it will detect that there's a redis.

However, internally the redis sends the ip address of the other redis to contact so it will send the ip address of the docker container to my NodeJs application, for example 172.10.20.30:7002, my application try to reach this ip 172.10.20.30:7002 but it fails and I end up in a endless connection loop.

with new versions of the ioredis library I can create a natMap that will resolve my problem.

const cluster = new Redis.Cluster(
  [
    {
      host: "203.0.113.73",
      port: 30001,
    },
  ],
  {
    natMap: {
      "10.0.1.230:30001": { host: "203.0.113.73", port: 30001 },
      "10.0.1.231:30001": { host: "203.0.113.73", port: 30002 },
      "10.0.1.232:30001": { host: "203.0.113.73", port: 30003 },
    },
  }
);

however I can't update this dependancy on the applications because it will affect other things

I need to find a way to bind the redis containers with the host IP address in order to not have this problem but I don't know how to do it or if it's even possible with my level of knowledge.

Here's what I do to create my redis cluster

docker network create --driver bridge redline;
for ind in `seq 1 6`; do \
 docker run -d \
 -v $PWD/redis.conf:/usr/local/etc/redis/redis.conf \
 --name "redis-$ind" \
 --net redline \
 -p "700$ind:6379" \
 redis redis-server /usr/local/etc/redis/redis.conf; \
done;

docker exec -it redis-1 redis-cli --cluster  create redis-1:6379 redis-2:6379 redis-3:6379 redis-4:6379 redis-5:6379 redis-6:6379  --cluster-replicas 1

here's the redis.conf used

bind 0.0.0.0
port 6379
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

here's how I instanciate my redis cluster in my nodejs application

  const redisClient = {
    redis: {
      createClientFactory: () => {
        return new Redis.Cluster(
           {
              port: 7001,
             host: "127.0.0.1",
            },
              {
              port: 7002,
              host: "127.0.0.1",
              }[...]
         , {
          clusterRetryStrategy: (times) => {
            return Math.min(1000 * times * 2, 60000)
          },
        })
      },
    },
  }
  redis.on('connect', () => {
    console.info('Connected to Redis')
  })

It successfully connect the first time, but when it reach the unreachable ip it just loops to the 'Connected to Redis' message because it loop on connect event but never really connects.

0

There are 0 best solutions below