Cloud Native 12 min read

Build a Cloud‑Native Redis Pub/Sub App with Dapr, Docker Compose, and NestJS

This step‑by‑step guide shows how to create a distributed Redis Pub/Sub application using Dapr, Docker Compose, and NestJS, covering project setup, Dapr placement, Redis publisher, component definition, sidecars, subscription configuration, testing, and CloudEvents JSON handling.

Hacker Afternoon Tea
Hacker Afternoon Tea
Hacker Afternoon Tea
Build a Cloud‑Native Redis Pub/Sub App with Dapr, Docker Compose, and NestJS

Overview

Dapr (Distributed Application Runtime) is a portable, event‑driven runtime that enables resilient stateless or stateful applications to run on cloud or edge platforms and supports multiple languages and frameworks.

Step‑by‑step implementation

1. Create project directory

mkdir dapr-nestjs-redis-pub-sub

2. Initialise Docker Compose

Create docker-compose.yml in the project root.

version: "3.5"
services:
  dapr-placement:
    image: "daprio/dapr"
    command: ["./placement","-port","50006"]

The placement service manages Dapr actor routing and acts as a message broker for the runtime.

3. Add Redis publisher service

redis-publisher:
    image: redis
    restart: always
    depends_on:
      - dapr-placement

4. Define Dapr Pub/Sub component

mkdir -p dapr/components
cd dapr/components
cat > redis-pubsub.yaml <<'EOF'
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: redis-pubsub
  namespace: default
spec:
  type: pubsub.redis
  version: v1
  metadata:
    - name: redisHost
      value: redis-publisher:6379
    - name: redisPassword
      value: ""
EOF

This component tells Dapr to use the Redis instance at redis-publisher:6379 for Pub/Sub.

5. Add Redis Dapr sidecar

redis-dapr-sidecar:
    image: "daprio/daprd:edge"
    command: [
      "./daprd",
      "-app-id","redis-publisher",
      "-app-port","6379",
      "-dapr-http-port","5000",
      "-components-path","/components",
      "-placement-host-address","dapr-placement:50006"
    ]
    volumes:
      - "./dapr/components/:/components"
    depends_on:
      - redis-publisher
    network_mode: "service:redis-publisher"

The sidecar forwards traffic from the Redis container to Dapr and registers the component.

6. Create NestJS subscriber service

npm i -g @nestjs/cli
nest new nest-subscriber

Use yarn as the package manager. Replace src/app.controller.ts with:

import { Controller, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Post('/redis-publisher')
  async postRedisPub(@Body() reqBody) {
    console.log(`Redis published ${JSON.stringify(reqBody)}`);
    return `NestJS subscriber received ${reqBody} publish`;
  }
}

7. Dockerfile for NestJS server

FROM node:16.13.0-alpine
WORKDIR "/app"
COPY ./nest-subscriber/package.json ./
RUN yarn install
COPY ./nest-subscriber .
RUN yarn run build
EXPOSE 3000
CMD ["yarn","start:prod"]

8. Add NestJS service to Docker Compose

nest-subscriber:
    image: "nest-subscriber:latest"
    depends_on:
      - redis-publisher
      - dapr-placement
    restart: always

9. Create Dapr subscription

mkdir -p dapr/subscriptions
cd dapr/subscriptions
cat > redis-subscription.yaml <<'EOF'
apiVersion: dapr.io/v1alpha1
kind: Subscription
metadata:
  name: nest-redis-sub
spec:
  topic: nest-redis-pub-topic
  route: /redis-publisher
  pubsubname: redis-pubsub
  scopes:
    - nest-subscriber
EOF

The subscription instructs Dapr to invoke /redis-publisher on the NestJS service whenever the topic nest-redis-pub-topic is published.

10. Add sidecar for NestJS subscriber

nest-subscriber-dapr-sidecar:
    image: "daprio/daprd:edge"
    command: [
      "./daprd",
      "-app-id","nest-subscriber",
      "-app-port","3000",
      "-components-path","/components",
      "-placement-host-address","dapr-placement:50006"
    ]
    volumes:
      - "./dapr/components/:/components"
    depends_on:
      - nest-subscriber
    network_mode: "service:nest-subscriber"

11. Test the flow

curl --location --request POST 'http://localhost:5001/v1.0/publish/redis-pubsub/nest-redis-pub-topic' \
  --header 'Content-Type: application/json' \
  --data-raw '{"hello":"world"}'

Dapr forwards the request to the Redis sidecar, which publishes the message. Initially the NestJS subscriber receives an empty JSON object ( {}).

12. Enable NestJS to parse CloudEvents JSON

yarn add body-parser
import * as bodyParser from 'body-parser';
...
app.use(bodyParser.json({ type: 'application/cloudevents+json' }));
app.use(bodyParser.json());

After adding the parser, the subscriber correctly processes the CloudEvents payload and logs the received message.

13. Full docker‑compose.yaml

version: "3.5"
services:
  dapr-placement:
    image: "daprio/dapr"
    command: ["./placement","-port","50006"]

  redis-publisher:
    image: redis
    depends_on:
      - dapr-placement
    restart: always
    ports:
      - 5001:5000

  redis-dapr-sidecar:
    image: "daprio/daprd:edge"
    command: [
      "./daprd",
      "-app-id","redis-publisher",
      "-app-port","6379",
      "-dapr-http-port","5000",
      "-components-path","/components",
      "-placement-host-address","dapr-placement:50006"
    ]
    volumes:
      - "./dapr/components/:/components"
    depends_on:
      - redis-publisher
    network_mode: "service:redis-publisher"

  nest-subscriber:
    image: "nest-subscriber:latest"
    depends_on:
      - redis-publisher
      - dapr-placement
    restart: always

  nest-subscriber-dapr-sidecar:
    image: "daprio/daprd:edge"
    command: [
      "./daprd",
      "-app-id","nest-subscriber",
      "-app-port","3000",
      "-components-path","/components",
      "-placement-host-address","dapr-placement:50006"
    ]
    volumes:
      - "./dapr/components/:/components"
    depends_on:
      - nest-subscriber
    network_mode: "service:nest-subscriber"

Source code

https://github.com/Hacker-Linner/dapr-nestjs-redis-pub-sub.git

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

cloud nativeRedisPub/SubDocker ComposeNestJSdapr
Hacker Afternoon Tea
Written by

Hacker Afternoon Tea

You might find something interesting here ^_^

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.