Docker Compose Quick Start
==========================
The easiest way to try Waterstream locally is with Docker Compose.
This sets up a complete stack — Kafka, Waterstream, and a Kafka web UI — with a single command,
with no need to install Confluent Platform or any other dependencies.
Prerequisites
-------------
- `Docker `_ with the Compose plugin (v2 or newer).
- A Waterstream license file (optional) — without one, Waterstream runs in development mode,
limited to 1 node and 20 concurrent clients.
To remove these limits, `request a free development license `_
and place it in the same directory as ``waterstream.license``.
Stack overview
--------------
The ``docker-compose.yml`` below starts four services:
.. list-table::
:header-rows: 1
:widths: 20 80
* - Service
- Purpose
* - ``kafka``
- Apache Kafka in KRaft mode (no ZooKeeper required)
* - ``kafka-init``
- Short-lived container that creates the required Waterstream topics, then exits
* - ``waterstream``
- The Waterstream MQTT broker, listening on port 1883
* - ``kafka-ui``
- `Kafka UI `_ web interface on port 8080
Start the stack
---------------
1. Copy the ``docker-compose.yml`` below into an empty directory.
2. (Optional) Place your Waterstream license file in the same directory as ``waterstream.license``.
3. Run:
.. code-block:: bash
docker compose up
Once the stack is ready you should see Waterstream log ``MQTT server started`` — the broker is
then reachable at ``localhost:1883``. Open ``http://localhost:8080`` to explore topics and
messages in Kafka UI.
To stop the stack press ``Ctrl+C``, or run ``docker compose down`` to also remove the containers.
``docker-compose.yml``
----------------------
.. code-block:: yaml
:substitutions:
services:
kafka:
image: apache/kafka:4.2.0
environment:
KAFKA_NODE_ID: "1"
KAFKA_PROCESS_ROLES: "broker,controller"
KAFKA_LISTENERS: "PLAINTEXT://:9092,CONTROLLER://:9093"
KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT://kafka:9092"
KAFKA_CONTROLLER_LISTENER_NAMES: "CONTROLLER"
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT"
KAFKA_CONTROLLER_QUORUM_VOTERS: "1@kafka:9093"
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: "1"
CLUSTER_ID: "MkU3OEVBNTcwNTJENDM2Qk"
healthcheck:
test: ["CMD-SHELL", "/opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --list"]
interval: 10s
timeout: 5s
retries: 10
kafka-init:
image: apache/kafka:4.2.0
depends_on:
kafka:
condition: service_healthy
entrypoint: ["/bin/bash", "-c"]
command:
- |
/opt/kafka/bin/kafka-topics.sh --bootstrap-server kafka:9092 --create --if-not-exists \
--topic mqtt_sessions --partitions 5 --replication-factor 1 \
--config cleanup.policy=compact \
--config min.compaction.lag.ms=60000 --config delete.retention.ms=600000 &&
/opt/kafka/bin/kafka-topics.sh --bootstrap-server kafka:9092 --create --if-not-exists \
--topic mqtt_retained_messages --partitions 5 --replication-factor 1 \
--config cleanup.policy=compact \
--config min.compaction.lag.ms=60000 --config delete.retention.ms=600000 &&
/opt/kafka/bin/kafka-topics.sh --bootstrap-server kafka:9092 --create --if-not-exists \
--topic mqtt_connections --partitions 5 --replication-factor 1 \
--config cleanup.policy=delete --config retention.ms=600000 &&
/opt/kafka/bin/kafka-topics.sh --bootstrap-server kafka:9092 --create --if-not-exists \
--topic mqtt_messages --partitions 5 --replication-factor 1 \
--config retention.ms=86400000 &&
/opt/kafka/bin/kafka-topics.sh --bootstrap-server kafka:9092 --create --if-not-exists \
--topic __waterstream_heartbeat --partitions 5 --replication-factor 1 \
--config retention.ms=300000
waterstream:
image: waterstreamio/waterstream-kafka:|release|
depends_on:
kafka-init:
condition: service_completed_successfully
environment:
KAFKA_BOOTSTRAP_SERVERS: "PLAINTEXT://kafka:9092"
MQTT_PORT: "1883"
KAFKA_SESSIONS_TOPIC: "mqtt_sessions"
KAFKA_RETAINED_MESSAGES_TOPIC: "mqtt_retained_messages"
KAFKA_CONNECTIONS_TOPIC: "mqtt_connections"
KAFKA_MESSAGES_DEFAULT_TOPIC: "mqtt_messages"
ports:
- "1883:1883"
volumes:
- ./waterstream.license:/etc/waterstream.license:ro
kafka-ui:
image: provectuslabs/kafka-ui:latest
depends_on:
- kafka
ports:
- "8080:8080"
environment:
KAFKA_CLUSTERS_0_NAME: "local"
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: "kafka:9092"
Test the setup
--------------
Install `mosquitto-clients `_ (or any MQTT client) and run:
.. code-block:: bash
# Subscribe in one terminal
mosquitto_sub -h localhost -p 1883 -t "test/#" -v
# Publish from another terminal
mosquitto_pub -h localhost -p 1883 -t "test/hello" -m "Hello from Waterstream"
You should see the message appear in the subscriber terminal.
Check ``http://localhost:8080`` to browse the ``mqtt_messages`` topic and confirm the message
was stored in Kafka.
More configuration options are documented in :doc:`configGuide`.