Getting Started with Dapr: Build Cloud‑Native Node.js Microservices from Scratch
This step‑by‑step guide shows how to install the Dapr CLI, initialize local Redis and Zipkin containers, configure component files, and use Dapr’s APIs to perform service invocation, state management, pub/sub, bindings, and secrets management in a Node.js microservice application, complete with code snippets and Docker commands.
Install Dapr CLI
macOS (Dapr 1.8):
sudo curl -fsSL https://raw.githubusercontent.com/dapr/cli/master/install/install.sh | /bin/bashLinux/Windows installation instructions are available at the official documentation URL:
https://docs.dapr.io/getting-started/install-dapr-cli/
Initialize Dapr locally
The dapr init command creates the following resources:
A Redis container for state storage and pub/sub.
A Zipkin container for tracing.
A default components folder with YAML definitions for state, pub/sub, and tracing.
A Dapr placement service container for actor support.
Run the initialization CLI command
dapr initVerify Dapr version
dapr -v
CLI version: 1.8.0
Runtime version: 1.8.0Validate running containers
After dapr init the containers daprio/dapr, openzipkin/zipkin and redis should be running. Verify with Docker commands such as docker ps or by inspecting the images.
Use Dapr HTTP API
Run a Dapr sidecar
dapr run --app-id myapp --dapr-http-port 3500This starts a sidecar listening on port 3500 for the application myapp. The default component definitions created by dapr init are used.
Save state
curl -X POST -H "Content-Type: application/json" -d '[{ "key": "name", "value": "Bruce Wayne"}]' http://localhost:3500/v1.0/state/statestoreGet state
curl http://localhost:3500/v1.0/state/statestore/nameInspect state in Redis
docker exec -it dapr_redis redis-cli
keys *
"myapp||name"
hgetall "myapp||name"
exitDelete state
curl -v -X DELETE -H "Content-Type: application/json" http://localhost:3500/v1.0/state/statestore/nameHands‑on examples
1. Service Invocation
Clone the quickstarts repository and run the order‑processor service with Dapr:
git clone https://github.com/dapr/quickstarts.git
cd service_invocation/javascript/http/order-processor
npm install
dapr run --app-port 5001 --app-id order-processor --app-protocol http --dapr-http-port 3501 -- npm startIn a separate terminal, start the checkout service:
cd ../../checkout
npm install
dapr run --app-id checkout --app-protocol http --dapr-http-port 3500 -- npm startService calls are made by adding the dapr-app-id header to HTTP requests:
let axiosConfig = { headers: { "dapr-app-id": "order-processor" } };
const res = await axios.post(`${DAPR_HOST}:${DAPR_HTTP_PORT}/orders`, order, axiosConfig);
console.log("Order passed: " + res.config.data);2. State Management
Navigate to the state‑management example, install dependencies, and run the service with a Dapr sidecar:
cd state_management/javascript/sdk/order-processor
npm install
dapr run --app-id order-processor --components-path ../../../components/ -- npm run startJavaScript SDK code that saves, retrieves, and deletes an order in the Redis‑backed statestore component:
const client = new DaprClient(DAPR_HOST, DAPR_HTTP_PORT);
client.state.save(STATE_STORE_NAME, [{ key: orderId.toString(), value: order }]);
client.state.get(STATE_STORE_NAME, orderId.toString()).then(val => console.log("Getting Order:", val));
client.state.delete(STATE_STORE_NAME, orderId.toString());3. Pub/Sub
Run the order‑processor subscriber:
dapr run --app-port 5001 --app-id order-processing --app-protocol http --dapr-http-port 3501 --components-path ../../../components -- npm run startRun the checkout publisher:
dapr run --app-id checkout --app-protocol http --dapr-http-port 3500 --components-path ../../../components -- npm run start
await client.pubsub.publish(PUBSUB_NAME, PUBSUB_TOPIC, order);
console.log("Published data: " + JSON.stringify(order));Pub/sub component definition ( pubsub.yaml) used by the example:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: order_pub_sub
spec:
type: pubsub.redis
version: v1
metadata:
- name: redisHost
value: localhost:6379
- name: redisPassword
value: ""4. Input and Output Bindings
Start the PostgreSQL Docker container defined in bindings/db/docker‑compose.yml:
cd bindings/db
docker compose upRun the Cron binding that triggers a batch job every 10 seconds:
cd bindings/javascript/sdk/batch
npm install
dapr run --app-id batch-sdk --app-port 5002 --dapr-http-port 3500 --components-path ../../../components -- node index.jsBatch job reads orders.json, builds an INSERT statement, and sends it to the PostgreSQL output binding ( binding‑postgres.yaml):
async function processBatch() {
const orders = JSON.parse(fs.readFileSync('../../orders.json', 'utf8')).orders;
orders.forEach(order => {
const sqlCmd = `insert into orders (orderid, customer, price) values (${order.orderid}, '${order.customer}', ${order.price});`;
const payload = { sql: sqlCmd };
client.binding.send(postgresBindingName, "exec", "", payload);
});
}Cron binding component ( binding‑cron.yaml) definition:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: cron
namespace: quickstarts
spec:
type: bindings.cron
version: v1
metadata:
- name: schedule
value: "@every 10s"PostgreSQL output binding component ( binding‑postgres.yaml) definition:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: sqldb
namespace: quickstarts
spec:
type: bindings.postgres
version: v1
metadata:
- name: url
value: "user=postgres password=docker host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10"5. Secrets Management
Local file‑based secret store component ( local‑secret‑store.yaml):
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: localsecretstore
namespace: default
spec:
type: secretstores.local.file
version: v1
metadata:
- name: secretsFile
value: secrets.json
- name: nestedSeparator
value: ":"Secret definition ( secrets.json): { "secret": "YourPasskeyHere" } JavaScript SDK code that retrieves the secret:
const DAPR_SECRET_STORE = "localsecretstore";
const SECRET_NAME = "secret";
async function main() {
const secret = await client.secret.get(DAPR_SECRET_STORE, SECRET_NAME);
console.log("Fetched Secret: " + JSON.stringify(secret));
}Official example repository
All demo source code is available at:
https://github.com/dapr/quickstarts.git
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
