Skip to content

Demo Environment Setup Guide

Demo Environment Setup Guide

This section provides a step-by-step guide to set up a complete IoT demonstration environment. By the end of this section, you will be able to:

  • Deploy the entire IoT backend stack in under 10 minutes using Docker Compose
  • Verify each component is working correctly
  • Perform basic MQTT publish-subscribe tests
  • Access Node-RED, InfluxDB, and Grafana interfaces
  • Prepare the environment for customer demonstrations

Before starting, ensure the following are available:

  • Docker (version 24.0 or newer): Install Docker
  • Docker Compose (version 2.20 or newer): Included with Docker Desktop, or install separately on Linux
  • A computer with at least 4 GB RAM and 10 GB free disk space
  • Internet connection for pulling container images (first-time setup: ~1 GB download)
  • ESP32 board (optional for initial testing, MQTT client tools can simulate devices)

Open a terminal and run:

Terminal window
docker --version
docker compose version

Expected output (versions may vary):

Docker version 27.0.0, build abcdef1
Docker Compose version v2.29.0

If Docker is not installed, download Docker Desktop from docker.com and follow the installation wizard.

Create a directory for the demo environment:

Terminal window
mkdir ~/iot-demo
cd ~/iot-demo

Step 2: Create Docker Compose Configuration

Section titled “Step 2: Create Docker Compose Configuration”

Create a file named docker-compose.yml in the ~/iot-demo directory:

version: "3.8"
services:
# MQTT Broker
mosquitto:
image: eclipse-mosquitto:2
container_name: mosquitto
ports:
- "1883:1883"
- "8883:8883"
volumes:
-./mosquitto/config:/mosquitto/config
-./mosquitto/data:/mosquitto/data
-./mosquitto/log:/mosquitto/log
restart: unless-stopped
# Node-RED Automation Engine
nodered:
image: nodered/node-red:4
container_name: nodered
ports:
- "1880:1880"
volumes:
-./nodered/data:/data
environment:
- TZ=UTC
restart: unless-stopped
depends_on:
- mosquitto
# InfluxDB Time-Series Database
influxdb:
image: influxdb:2
container_name: influxdb
ports:
- "8086:8086"
volumes:
-./influxdb/data:/var/lib/influxdb2
-./influxdb/config:/etc/influxdb2
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=admin
- DOCKER_INFLUXDB_INIT_PASSWORD=admin123
- DOCKER_INFLUXDB_INIT_ORG=iot-demo
- DOCKER_INFLUXDB_INIT_BUCKET=sensor-data
- DOCKER_INFLUXDB_INIT_RETENTION=30d
restart: unless-stopped
# Grafana Visualization
grafana:
image: grafana/grafana:11
container_name: grafana
ports:
- "3000:3000"
volumes:
-./grafana/data:/var/lib/grafana
-./grafana/config:/etc/grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin123
- GF_INSTALL_PLUGINS=
restart: unless-stopped
depends_on:
- influxdb

Configuration notes:

  • The MQTT broker is exposed on port 1883 (unencrypted) for local development. For production, use port 8883 with TLS.
  • InfluxDB is initialized with a demo organization, bucket, and credentials. These should be changed for production.
  • Grafana is pre-configured with admin credentials. Change these for any non-demo use.
  • All services use persistent volumes so data survives container restarts.

Create the Mosquitto configuration directory and file:

Terminal window
mkdir -p mosquitto/config

Create mosquitto/config/mosquitto.conf:

# Mosquitto Configuration for IoT Demo
listener 1883
protocol mqtt
# Allow anonymous access for demo purposes
allow_anonymous true
# Persistence
persistence true
persistence_location /mosquitto/data/
# Logging
log_dest file /mosquitto/log/mosquitto.log
log_dest stdout
log_type all
# Maximum connections
max_connections 1000

Important security note: The configuration above allows anonymous access for demo purposes. In any production or internet-facing deployment, always:

  • Set allow_anonymous false
  • Configure username/password authentication
  • Use TLS encryption (see Section 16 for details)

Create the data directories:

Terminal window
mkdir -p mosquitto/data mosquitto/log

Start all services:

Terminal window
cd ~/iot-demo
docker compose up -d

Docker will pull all images (first time only) and start the containers. This typically takes 2-5 minutes depending on internet speed.

Expected output:

[+] Running 5/5
✔ Container mosquitto Started
✔ Container influxdb Started
✔ Container nodered Started
✔ Container grafana Started

Check the status of all containers:

Terminal window
docker compose ps

Expected output:

NAME IMAGE STATUS PORTS
mosquitto eclipse-mosquitto:2 Up 2 minutes 0.0.0.0:1883->1883/tcp, 0.0.0.0:8883->8883/tcp
nodered nodered/node-red:4 Up 2 minutes 0.0.0.0:1880->1880/tcp
influxdb influxdb:2 Up 2 minutes 0.0.0.0:8086->8086/tcp
grafana grafana/grafana:11 Up 2 minutes 0.0.0.0:3000->3000/tcp

InfluxDB is automatically initialized with the credentials specified in docker-compose.yml. To verify:

  1. Open a browser and navigate to http://localhost:8086
  2. Log in with username admin and password admin123
  3. You should see the InfluxDB UI showing the sensor-data bucket

If the automatic setup did not complete (first-time initialization can be timing-sensitive), complete it manually:

  1. Click “Get Started”
  2. Enter: Username admin, Password admin123, Organization iot-demo, Bucket sensor-data
  3. Click “Continue”

Retrieve the API token (needed for Node-RED to write data):

Terminal window
docker exec influxdb influx auth list --org iot-demo

Copy the token string (a long hexadecimal value). Save it — you will need it when configuring Node-RED in later sections.

  1. Open a browser and navigate to http://localhost:1880
  2. You should see the Node-RED flow editor interface
  3. No authentication is configured by default (in production, enable admin authentication)

Quick verification test:

  1. Drag an “Inject” node (from the left palette) onto the workspace
  2. Drag a “Debug” node onto the workspace
  3. Connect the Inject node output to the Debug node input
  4. Click the “Deploy” button (top right)
  5. Click the button on the left side of the Inject node
  6. Check the Debug sidebar (right panel) — you should see timestamp messages appearing
  1. Open a browser and navigate to http://localhost:3000
  2. Log in with username admin and password admin123
  3. Grafana will prompt you to change the password — click “Skip” for demo purposes

Add InfluxDB as a data source:

  1. Go to Connections → Data Sources → Add data source
  2. Search for and select “InfluxDB”
  3. Configure:
  • Query Language: Flux
  • URL: http://influxdb:8086 (use the Docker service name, not localhost)
  • Organization: iot-demo
  • Token: (paste the token from Step 5)
  • Default Bucket: sensor-data
  1. Click “Save & Test” — you should see a “Data source is working” confirmation

To verify the MQTT broker is working, use MQTT command-line tools or MQTT Explorer.

Install MQTT clients if not already available:

Terminal window
# macOS
brew install mosquitto
# Ubuntu/Debian
sudo apt-get install mosquitto-clients

In one terminal, subscribe to a test topic:

Terminal window
mosquitto_sub -h localhost -p 1883 -t "demo/test" -v

In another terminal, publish a test message:

Terminal window
mosquitto_pub -h localhost -p 1883 -t "demo/test" -m '{"message":"Hello IoT Demo","timestamp":1712345678}'

The subscriber terminal should display:

demo/test {"message":"Hello IoT Demo","timestamp":1712345678}

MQTT Explorer is a free desktop application that provides a visual interface:

  1. Download and install MQTT Explorer
  2. Create a new connection:
  • Host: localhost
  • Port: 1883
  • No username/password (anonymous)
  1. Click “Connect”
  2. You will see a live view of all topics as data flows through the broker
  3. You can also publish test messages directly from the interface

To demonstrate the data pipeline without physical hardware, create a simulated sensor flow in Node-RED:

  1. In Node-RED, create a new flow by clicking ”+” next to the tab name
  2. Add these nodes:
  • Inject node (configured to repeat every 10 seconds)
  • Function node (to generate random sensor values)
  • MQTT Out node (to publish to the broker)

Configure the Inject node:

  • Payload: timestamp
  • Repeat: interval, every 10 seconds
  • Name: Every 10s

Configure the Function node with this JavaScript code:

// Generate random sensor data simulating an ESP32
const sensorData = {
device_id: "esp32_sim_01",
temperature: Math.round((20 + Math.random * 15) * 10) / 10, // 20-35°C
humidity: Math.round((40 + Math.random * 40) * 10) / 10, // 40-80%
light: Math.round(Math.random * 1000), // 0-1000 lux
battery: Math.round((80 + Math.random * 20) * 10) / 10, // 80-100%
timestamp: Date.now
};
msg.payload = sensorData;
msg.topic = "factory/zone1/environment";
return msg;

Configure the MQTT Out node:

  • Server: localhost:1883 (or use the Mosquitto broker node)
  • Topic: factory/zone1/environment
  • QoS: 1
  • Name: Publish Sensor Data

Connect: Inject → Function → MQTT Out

Deploy the flow. You should see data appearing in the MQTT Explorer under the factory/zone1/environment topic.

To complete the data pipeline, add InfluxDB storage:

  1. Install the InfluxDB node palette:
  • Click the hamburger menu (top right) → Manage palette
  • Go to the “Install” tab
  • Search for node-red-contrib-influxdb and install
  1. Add an InfluxDB Out node to your flow
  2. Configure the InfluxDB node:
  • Server: Create a new InfluxDB server config
  • URL: http://influxdb:8086
  • Token: (paste the InfluxDB API token from Step 5)
  • Organization: iot-demo
  • Bucket: sensor-data
  1. Wire: MQTT In → Function → InfluxDB Out

A complete minimal flow now looks like:

Inject (10s) → Function (generate data) → MQTT Out (publish)
MQTT In (subscribe) → InfluxDB Out (store)

After completing all steps, verify each component:

  • Docker: All 4 containers are running (docker compose ps)
  • Mosquitto: MQTT broker accepts connections on port 1883 (mosquitto_sub test)
  • Node-RED: Flow editor accessible at http://localhost:1880
  • InfluxDB: Web UI accessible at http://localhost:8086, bucket sensor-data exists
  • Grafana: Login at http://localhost:3000, InfluxDB data source configured
  • Data Pipeline: Simulated sensor data flows from Inject → InfluxDB (visible in InfluxDB Data Explorer)

To stop the demo environment:

Terminal window
cd ~/iot-demo
docker compose down

To stop and remove all data (clean slate):

Terminal window
cd ~/iot-demo
docker compose down -v
rm -rf mosquitto/data mosquitto/log nodered/data influxdb/data grafana/data

Symptom: docker compose up -d returns exit code for one or more containers.

Check logs:

Terminal window
docker compose logs <service-name>

Common cause: Port already in use.

Terminal window
# Check what is using port 1883
lsof -i :1883
# Stop the conflicting service or change the port mapping in docker-compose.yml

Symptom: mosquitto_sub returns “Connection refused”.

Verify the broker is running:

Terminal window
docker compose ps mosquitto

Check Mosquitto logs:

Terminal window
docker compose logs mosquitto

Try connecting with verbose output:

Terminal window
mosquitto_sub -h localhost -p 1883 -t "test" -d

Symptom: InfluxDB Out node shows “Connection error”.

Ensure both are on the same Docker network — Docker Compose automatically creates a network for all services, so using the service name influxdb (not localhost) in the InfluxDB node configuration resolves this.

Symptom: Dashboard panels display “No data” or “Query error”.

Check:

  1. Is the InfluxDB data source configured with the correct URL? Use http://influxdb:8086 (not localhost).
  2. Is the token correct? (Retrieve with docker exec influxdb influx auth list)
  3. Are there data points in the bucket? Check in InfluxDB Data Explorer.
  4. Is the query using the correct bucket name? Default is sensor-data.

For a complete demo experience with physical hardware, the following components are recommended:

ComponentRecommended ModelApprox. CostSearch Term
ESP32 boardESP32 DevKit V1$5-8”ESP32 WiFi Bluetooth Development Board”
Temperature sensorDHT22$3-5”DHT22 Temperature Humidity Sensor Module”
Light sensorBH1750$2-4”BH1750 Light Intensity Sensor Module GY-302”
Relay module2-channel 5V relay$3-6”5V 2-Channel Relay Module Optocoupler”
Breadboard + wires830-point breadboard$5-8”Breadboard 830 Points + 65 Jumper Wires”
USB cableUSB-A to Micro-USB$2-4”USB to Micro USB Data Cable for ESP32”
Total$20-35

This hardware kit allows you to demonstrate:

  • Temperature and humidity monitoring (DHT22 → ESP32 → MQTT → Grafana)
  • Light-based automation (BH1750 → ESP32 → MQTT → relay control)
  • Simple ON/OFF control (Node-RED → MQTT → ESP32 → relay → LED)

This section provided a complete, repeatable setup for an IoT demonstration environment:

  • Deployed a 4-service Docker stack (Mosquitto, Node-RED, InfluxDB, Grafana)
  • Configured each service with appropriate settings for demo use
  • Verified MQTT communication using CLI tools and MQTT Explorer
  • Created a simulated sensor data pipeline from Node-RED to InfluxDB
  • Prepared the environment for customer demonstrations

The entire setup process takes under 10 minutes and requires only Docker on the host machine. This environment will be used throughout the training to support the project-based chapters (Chapters 02-05, 10-14).