Redis from Express
Using Redis from a Node.js Express App via Docker Compose
Updated: 03 September 2023
Setup Project
Init an NPM project with Redis and Express:
1mkdir express-redis2cd express-redis3npm init -y4
5npm install express redis
Create Container
To start a Redis Container run:
1docker run --name node-redis -p 6379:6379 -d redis redis-server --appendonly yes
Test A DB Query
The following code should create a key-value pair on redis, you can add this to a file called db.js
db.js
1const redis = require('redis')2const client = redis.createClient()3
4client.on('error', function (error) {5 console.error(error)6})7
8client.set('bob', 'i am bob', redis.print)9client.get('bob', redis.print)
Or, if you’re feeling that the default client is sketchy you can use this with the explicit url:
1const client = redis.createClient({2 url: ' redis://localhost:6379',3})
Either way, you can run this using node db.js
which should output the creation success
View the Data from DB
You can login to the redis container via docker, and then from the command line you can log into the db itself with:
1redis-cli
And then list all the keys using:
1keys *
And we can even get the data from the DB using the get
command:
1get bob
Create an Express Client
A simple express client which will do key-value creates and lookups can be defined in an index.js
file:
index.js
1const express = require('express')2const redis = require('redis')3
4const port = process.env.PORT || 80805
6const app = express()7
8app.use(express.text())9
10const client = redis.createClient({11 url: 'redis://localhost:6379',12})13
14client.on('error', function (error) {15 console.error(error)16})17
18app.get('/', (req, res) => {19 console.log('request at URL')20 res.send('hello nabeeel from port ' + port)21})22
23app.get('/:key', (req, res) => {24 const key = req.params.key25 client.get(key, (error, reply) => {26 if (error) res.send('Error')27 else res.send(reply)28 })29})30
31app.post('/:key', (req, res) => {32 const key = req.params.key33 const data = req.body34 client.set(key, data, (error, reply) => {35 if (error) res.send('Error')36 else res.send(reply)37 })38})39
40app.posts41
42app.listen(port, () => {43 console.log('app is listening on port ' + port)44})
You can then just run the web server with:
1node index.js
The Dockerfile
for the above app is so:
1FROM node:142
3COPY package.json .4COPY package-lock.json .5RUN npm ci6
7COPY . .8
9EXPOSE 808010CMD ["npm", "start"]
Test the App
And you should then be able to make requests to the application from something like Postman for creating and retreiving a record
Set
With the server running you can create a new item with:
1POST localhost:8080/my-test-key2
3BODY "my test data"4
5RESPONSE "OK"
Get
You can then get the value using the key with:
1GET localhost:8080/my-test-key2
3RESPONSE "my test data"
Setting Up Compose
Before moving on please ensure you stop the Redis container we previously started with
docker container stop node-redis
Since we’re using Docker, it would be great to configure our application using a Docker compose file. In the compose file we’ll define a web
and redis
service and will provide the Redis URL in the environment for our Express app, the service config for web
is:
1web:2 image: express-app3 build:4 context: .5 dockerfile: ./Dockerfile6 environment:7 NODE_ENV: production8 REDIS_URL: redis://redis:63799 ports:10 - 8080:8080
And for the redis
service it’s pretty much the same as what we provided to the container we started with the command line:
1redis:2 image: redis3 environment:4 # ALLOW_EMPTY_PASSWORD is recommended only for development.5 - ALLOW_EMPTY_PASSWORD=yes6 - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL7 ports:8 - 6379:63799 volumes:10 - .db:/data11 restart: always12 entrypoint: redis-server --appendonly yes
So the overall compose file will now be:
docker-compose.yml
1version: '3.4'2
3services:4 web:5 image: express-app6 build:7 context: .8 dockerfile: ./Dockerfile9 environment:10 NODE_ENV: production11 REDIS_URL: redis://redis:637912 ports:13 - 8080:808014
15 redis:16 image: redis17 environment:18 # ALLOW_EMPTY_PASSWORD is recommended only for development.19 - ALLOW_EMPTY_PASSWORD=yes20 - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL21 ports:22 - 6379:637923 volumes:24 - .db:/data25 restart: always26 entrypoint: redis-server --appendonly yes
Access Redis from Within Network
Now, it should be possible for us to access the redis instance using Service Discovery within the compose network, to do this we’ll use the REDIS_URL
environment variable we defined above which will make a connection to redis://redis:6379
which will be resolved within the docker network that our application will run in
We can modify our client app by updating the connection to Redis as follows:
index.js
1const redisUrl = process.env.REDIS_URL2
3// other stuff4
5const client = redis.createClient({6 url: redisUrl,7})
So the final file will now be:
index.js
1const express = require('express')2const redis = require('redis')3
4const port = process.env.PORT || 80805const redisUrl = process.env.REDIS_URL6
7const app = express()8
9app.use(express.text())10
11const client = redis.createClient({12 url: redisUrl,13})14
15client.on('error', function (error) {16 console.error(error)17})18
19app.get('/', (req, res) => {20 console.log('request at URL')21 res.send('hello nabeeel from port ' + port)22})23
24app.get('/:key', (req, res) => {25 const key = req.params.key26 client.get(key, (error, reply) => {27 if (error) res.send('Error')28 else res.send(reply)29 })30})31
32app.post('/:key', (req, res) => {33 const key = req.params.key34 const data = req.body35 client.set(key, data, (error, reply) => {36 if (error) res.send('Error')37 else res.send(reply)38 })39})40
41app.listen(port, () => {42 console.log('app is listening on port ' + port)43})
And you should be able to run this all with:
1docker-compose up
And this will run Redis as well as your Application, and you are pretty much good to use the application exactly as we did before addding the compose setup and will connect our application to Redis from within the docker network