docker.recipes

IoT Sensor Platform

intermediate

IoT platform with EMQX MQTT broker, TimescaleDB for time-series, Telegraf collection, and Grafana

Overview

EMQX is a massively scalable, open-source MQTT broker built on Erlang/OTP that can handle millions of concurrent IoT device connections with sub-millisecond latency. As a distributed message broker implementing MQTT 3.1.1 and 5.0 protocols, EMQX excels at ingesting high-velocity sensor data from IoT devices, industrial equipment, and smart home systems. Originally developed by EMQ Technologies, it has become the backbone for IoT platforms requiring enterprise-grade reliability and horizontal scaling capabilities. This IoT sensor platform combines EMQX's high-performance MQTT brokering with TimescaleDB's PostgreSQL-based time-series storage, creating a powerful data pipeline for sensor telemetry. Telegraf acts as the bridge, subscribing to MQTT topics from EMQX and writing structured time-series data into TimescaleDB's hypertables with automatic time-based partitioning. Grafana completes the stack by providing rich visualizations and alerting capabilities, connecting directly to TimescaleDB using standard PostgreSQL drivers for complex analytical queries across your sensor data. This combination is ideal for IoT developers and system integrators who need PostgreSQL compatibility alongside time-series optimization, allowing them to join sensor data with relational information like device metadata, user accounts, or inventory systems. Unlike pure time-series databases, TimescaleDB's full SQL support enables complex analytics while EMQX handles the massive concurrent connection loads that industrial IoT deployments demand, making this stack perfect for smart building management, industrial monitoring, or large-scale sensor networks.

Key Features

  • EMQX clustering support for horizontal scaling to millions of concurrent MQTT connections
  • TimescaleDB hypertables with automatic time-based partitioning for optimal sensor data storage
  • Built-in EMQX rule engine for real-time data processing and routing based on MQTT topics
  • TimescaleDB continuous aggregates for pre-computed sensor data rollups and statistics
  • EMQX WebSocket and MQTT-over-SSL support for browser-based IoT applications
  • PostgreSQL compatibility allowing complex JOINs between sensor data and device metadata
  • Telegraf's extensive input plugins supporting 200+ data sources beyond MQTT
  • TimescaleDB compression achieving 90%+ storage reduction for historical sensor data

Common Use Cases

  • 1Smart building management systems collecting temperature, humidity, and occupancy data from hundreds of sensors
  • 2Industrial IoT monitoring for manufacturing equipment with predictive maintenance analytics
  • 3Environmental monitoring networks tracking air quality, weather, and pollution across multiple locations
  • 4Smart agriculture platforms monitoring soil moisture, temperature, and crop health sensors
  • 5Fleet management systems tracking vehicle telemetry, GPS coordinates, and engine diagnostics
  • 6Home automation platforms managing smart thermostats, security sensors, and energy monitors
  • 7Retail analytics collecting foot traffic, temperature, and inventory sensor data across store chains

Prerequisites

  • Minimum 4GB RAM recommended (2GB for TimescaleDB, 1GB for EMQX, 512MB for Grafana)
  • Available ports: 1883 (MQTT), 5432 (PostgreSQL), 3000 (Grafana), 18083 (EMQX Dashboard)
  • Basic understanding of MQTT protocol and topic structure for IoT device communication
  • Familiarity with PostgreSQL and SQL queries for TimescaleDB data analysis
  • Telegraf configuration knowledge for setting up MQTT consumer and PostgreSQL output plugins
  • Understanding of time-series data concepts like retention policies and data aggregation

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 emqx:
3 image: emqx/emqx:latest
4 container_name: emqx
5 restart: unless-stopped
6 ports:
7 - "1883:1883"
8 - "8083:8083"
9 - "8084:8084"
10 - "${EMQX_DASHBOARD:-18083}:18083"
11 environment:
12 - EMQX_NAME=emqx
13 - EMQX_HOST=127.0.0.1
14 volumes:
15 - emqx_data:/opt/emqx/data
16 - emqx_log:/opt/emqx/log
17
18 timescaledb:
19 image: timescale/timescaledb:latest-pg15
20 container_name: timescaledb
21 restart: unless-stopped
22 ports:
23 - "${TIMESCALE_PORT:-5432}:5432"
24 environment:
25 - POSTGRES_USER=${DB_USER}
26 - POSTGRES_PASSWORD=${DB_PASSWORD}
27 - POSTGRES_DB=iot
28 volumes:
29 - timescaledb_data:/var/lib/postgresql/data
30
31 telegraf:
32 image: telegraf:latest
33 container_name: telegraf
34 restart: unless-stopped
35 volumes:
36 - ./telegraf/telegraf.conf:/etc/telegraf/telegraf.conf:ro
37 depends_on:
38 - emqx
39 - timescaledb
40
41 grafana:
42 image: grafana/grafana:latest
43 container_name: iot-grafana
44 restart: unless-stopped
45 ports:
46 - "${GRAFANA_PORT:-3000}:3000"
47 environment:
48 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}
49 volumes:
50 - grafana_data:/var/lib/grafana
51 depends_on:
52 - timescaledb
53
54volumes:
55 emqx_data:
56 emqx_log:
57 timescaledb_data:
58 grafana_data:

.env Template

.env
1# IoT Sensor Platform
2EMQX_DASHBOARD=18083
3TIMESCALE_PORT=5432
4GRAFANA_PORT=3000
5
6# Database
7DB_USER=iot
8DB_PASSWORD=iot_password
9
10# Grafana
11GRAFANA_PASSWORD=admin

Usage Notes

  1. 1EMQX Dashboard at http://localhost:18083 (admin/public)
  2. 2MQTT broker at localhost:1883
  3. 3Grafana at http://localhost:3000
  4. 4Configure telegraf.conf for MQTT input and PostgreSQL output
  5. 5TimescaleDB optimized for time-series IoT data
  6. 6EMQX supports millions of concurrent connections

Individual Services(4 services)

Copy individual services to mix and match with your existing compose files.

emqx
emqx:
  image: emqx/emqx:latest
  container_name: emqx
  restart: unless-stopped
  ports:
    - "1883:1883"
    - "8083:8083"
    - "8084:8084"
    - ${EMQX_DASHBOARD:-18083}:18083
  environment:
    - EMQX_NAME=emqx
    - EMQX_HOST=127.0.0.1
  volumes:
    - emqx_data:/opt/emqx/data
    - emqx_log:/opt/emqx/log
timescaledb
timescaledb:
  image: timescale/timescaledb:latest-pg15
  container_name: timescaledb
  restart: unless-stopped
  ports:
    - ${TIMESCALE_PORT:-5432}:5432
  environment:
    - POSTGRES_USER=${DB_USER}
    - POSTGRES_PASSWORD=${DB_PASSWORD}
    - POSTGRES_DB=iot
  volumes:
    - timescaledb_data:/var/lib/postgresql/data
telegraf
telegraf:
  image: telegraf:latest
  container_name: telegraf
  restart: unless-stopped
  volumes:
    - ./telegraf/telegraf.conf:/etc/telegraf/telegraf.conf:ro
  depends_on:
    - emqx
    - timescaledb
grafana
grafana:
  image: grafana/grafana:latest
  container_name: iot-grafana
  restart: unless-stopped
  ports:
    - ${GRAFANA_PORT:-3000}:3000
  environment:
    - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}
  volumes:
    - grafana_data:/var/lib/grafana
  depends_on:
    - timescaledb

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 emqx:
5 image: emqx/emqx:latest
6 container_name: emqx
7 restart: unless-stopped
8 ports:
9 - "1883:1883"
10 - "8083:8083"
11 - "8084:8084"
12 - "${EMQX_DASHBOARD:-18083}:18083"
13 environment:
14 - EMQX_NAME=emqx
15 - EMQX_HOST=127.0.0.1
16 volumes:
17 - emqx_data:/opt/emqx/data
18 - emqx_log:/opt/emqx/log
19
20 timescaledb:
21 image: timescale/timescaledb:latest-pg15
22 container_name: timescaledb
23 restart: unless-stopped
24 ports:
25 - "${TIMESCALE_PORT:-5432}:5432"
26 environment:
27 - POSTGRES_USER=${DB_USER}
28 - POSTGRES_PASSWORD=${DB_PASSWORD}
29 - POSTGRES_DB=iot
30 volumes:
31 - timescaledb_data:/var/lib/postgresql/data
32
33 telegraf:
34 image: telegraf:latest
35 container_name: telegraf
36 restart: unless-stopped
37 volumes:
38 - ./telegraf/telegraf.conf:/etc/telegraf/telegraf.conf:ro
39 depends_on:
40 - emqx
41 - timescaledb
42
43 grafana:
44 image: grafana/grafana:latest
45 container_name: iot-grafana
46 restart: unless-stopped
47 ports:
48 - "${GRAFANA_PORT:-3000}:3000"
49 environment:
50 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}
51 volumes:
52 - grafana_data:/var/lib/grafana
53 depends_on:
54 - timescaledb
55
56volumes:
57 emqx_data:
58 emqx_log:
59 timescaledb_data:
60 grafana_data:
61EOF
62
63# 2. Create the .env file
64cat > .env << 'EOF'
65# IoT Sensor Platform
66EMQX_DASHBOARD=18083
67TIMESCALE_PORT=5432
68GRAFANA_PORT=3000
69
70# Database
71DB_USER=iot
72DB_PASSWORD=iot_password
73
74# Grafana
75GRAFANA_PASSWORD=admin
76EOF
77
78# 3. Start the services
79docker compose up -d
80
81# 4. View logs
82docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/iot-sensor-platform/run | bash

Troubleshooting

  • EMQX connection refused on port 1883: Check if EMQX container started properly and verify firewall rules allow MQTT traffic
  • Telegraf failing to connect to EMQX: Ensure MQTT input plugin configuration uses correct broker URL 'emqx:1883' for container networking
  • TimescaleDB connection errors from Grafana: Verify PostgreSQL service is running and use 'timescaledb:5432' as data source URL
  • High memory usage in TimescaleDB: Enable TimescaleDB compression on older chunks and configure appropriate retention policies for sensor data
  • EMQX dashboard shows authentication failures: Default credentials are admin/public, check client certificates if using SSL/TLS connections
  • Missing data in Grafana dashboards: Verify Telegraf is successfully writing to TimescaleDB by checking PostgreSQL logs and table row counts

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space