node.jsdockerdocker-composeredisdockerfile

Unable to connect redis/redis-stack with Node.js


I am following this documentation https://hub.docker.com/r/redis/redis-stack to connect to redis with Node.js. However, I keep getting this warning in my logs

redis-stack-1  | 9:M 09 Jun 2024 03:12:50.151 * <redisgears_2> Failed loading RedisAI API.
redis-stack-1  | 9:M 09 Jun 2024 03:12:50.151 * <redisgears_2> RedisGears v2.0.20, sha='9b737886bf825fe29ddc2f8da81f73cbe0b4e858', build_type='release', built_for='Linux-ubuntu22.04.aarch64', redis_version:'7.2.4', enterprise:'false'.

Following is my folder structure

enter image description here

Following is DockerFile

# Use the official Node.js image from the Docker Hub
FROM node:14
# Create and set the working directory inside the container
WORKDIR /usr/src/app
# Copy package.json and package-lock.json files
COPY package*.json ./
# Install the dependencies
RUN npm install
# Expose the port the app runs on
EXPOSE 3000
# Start the application
CMD ["npm", "run", "dev"]

Following is docker-compose.yml file

version: "3.6"
services:
  my-node-app:
    image: my-node-app
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/usr/src/app
  redis-stack:
    image: redis/redis-stack:latest
    environment:
      - REDIS_ARGS="--requirepass mypassword"
    ports:
      - 6379:6379
      - 8001:8001
    healthcheck:
      test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
    volumes:
      - redis_data:/data
volumes:
  redis_data:

This is my index.js file

const express = require("express");
const redis = require("redis");
const app = express();
const port = 3000;

// Create Redis client with Docker Compose service name as hostname
const client = redis.createClient({
  host: "redis-stack", // Use the service name from Docker Compose
  port: 6379,
  password: "mypassword", // Change this to your actual Redis password
});

client.on("connect", () => {
  console.log("Connected to Redis");

  // Example: Insert data into Redis after successful connection
  client.set("mykey", "Hello Redis!", (err, reply) => {
    if (err) {
      console.error("Error setting key in Redis:", err);
    } else {
      console.log("Key set successfully in Redis:", reply);
    }
  });
});

client.on("error", (err) => {
  console.error("Error connecting to Redis:", err);
});

app.get("/", (req, res) => {
  res.send("Hello Docker Compose!");
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});

Package.json

   {
      "name": "redis-node",
      "version": "1.0.0",
      "main": "index.js",
      "scripts": {
        "start": "node index.js",
        "dev": "nodemon index.js"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "description": "",
      "devDependencies": {
        "nodemon": "^3.1.3"
      },
      "dependencies": {
        "express": "^4.19.2",
        "redis": "^4.6.14"
      }
    }

Where am I going wrong with this?


Solution

  • Redis AI was removed from Redis Stack and is no longer supported. That said, Redis Gears can still work with it if it is present. If it's not present, Redis Gears will warn you of that fact. You can safely ignore this warning.

    What's more notable is that you are using Node Redis 3.x syntax with the Node Redis 4.x client. The version of Node Redis you are using does not support the callback syntax you are using. It now uses Promises.

    You're also not passing in the client configuration correctly. I think this changed between 3.x and 4.x as well.

    You can check out the documentation in the README for more details but here's the skinny on connecting to Redis and setting a key:

    /* create a client */
    const client = createClient({
      socket: {
        host: 'redi,s-stack'
        port: 6379
      },
      password: 'mypassword'
    })
    
    /* Add an error handler. Pptional but if you don't the process
       ends on and error */
    client.on('error', err => console.log('Redis Client Error', err))
    
    /* Connect to Redis. Note the await. */
    await client.connect()
    
    /* Use it with Promises */
    await client.set('key', 'value')
    const value = await client.get('key')
    

    Hope that helps!