KubeMQ
Deploy

Install KubeMQ with Docker

Run KubeMQ under Docker in depth — Compose, configuration, connectors, persistence, health checks, upgrade and backup.

Docker is recommended for development and testing only. For production, deploy on Kubernetes with Helm and the operator.

New here? Start with the Quickstart — it runs KubeMQ, opens the dashboard, and round-trips your first message in about 5 minutes. This page is the in-depth Docker reference: Compose, configuration, connectors, persistence, health checks, and standalone upgrade/rollback/backup.

Docker Compose

For a more structured setup, use Docker Compose. This configuration includes persistent storage and environment variable support.

docker-compose.yml

services:
  kubemq:
    image: europe-docker.pkg.dev/kubemq/images/kubemq:next
    container_name: kubemq
    hostname: kubemq
    ports:
      - "50000:50000"  # gRPC
      - "9090:9090"    # REST
      - "8080:8080"    # API & Dashboard
    environment:
      - KUBEMQ_TOKEN=${KUBEMQ_TOKEN:-}
    volumes:
      - kubemq-data:/kubemq/store
    restart: unless-stopped

volumes:
  kubemq-data:

Save this file and start KubeMQ:

Terminal
docker compose up -d

A downloadable version of this file is available at /docker-compose.yml.

Stop and remove

Terminal
docker compose down

To also remove persistent data:

Terminal
docker compose down -v

Configuration

KubeMQ is configured through environment variables. Pass them using the -e flag with docker run or the environment section in Docker Compose.

Common environment variables

VariableDefaultDescription
KUBEMQ_TOKENLicense key (required for standalone mode outside Kubernetes)
LOG_LEVEL2Log verbosity: 0=Trace 1=Debug 2=Info 3=Warn 4=Error 5=Fatal
API_PORT8080Dashboard and management API port
CONNECTORS_GRPC_PORT50000gRPC transport port
CONNECTORS_REST_PORT9090REST transport port
STORE_CLEAN_STOREfalseRemove stored data on startup
STORE_MAX_RETENTION1440Max message retention in minutes (default: 24 hours)
STORE_MAX_MESSAGES0Max messages per channel (0 = unlimited)
STORE_MAX_QUEUE_SIZE0Max queue size in bytes (0 = unlimited)
QUEUE_MAX_NUMBER_OF_MESSAGES1024Max messages per receive request
QUEUE_MAX_WAIT_TIMEOUT_SECONDS3600Max polling wait timeout in seconds

Example with configuration

docker run -d \  --name kubemq \  -p 50000:50000 \  -p 9090:9090 \  -p 8080:8080 \  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \  -e LOG_LEVEL=2 \  -e STORE_MAX_RETENTION=2880 \  europe-docker.pkg.dev/kubemq/images/kubemq:next

Sizing for local eval: a single container is light — 1-2 vCPU and 2 GB RAM is enough for local development and evaluation traffic on any of the four patterns. Scale up only if you drive sustained high-throughput persistence (Events Store, Queues, or the Kafka connector) with a large STORE_MAX_RETENTION. Production/cluster sizing lives in the Helm production checklist.

Ports

KubeMQ exposes three core network ports by default. Wire-protocol connectors are opt-in — they open additional ports only when you enable them.

PortProtocolServiceDescription
50000gRPC (HTTP/2)TransportPrimary SDK transport. All SDKs connect here by default.
9090HTTPREST / WebSocketREST API and WebSocket connections for subscriptions.
8080HTTPDashboard / APIWeb dashboard, health probes (/health, /ready), and Prometheus metrics (/metrics).

The gRPC port (50000) is the primary transport used by all KubeMQ SDKs. The REST port (9090) is useful for testing with cURL or when gRPC is not available. The dashboard port (8080) provides a management UI and health endpoints.

Enabling wire-protocol connectors

The seven wire-protocol connectors (MQTT, AMQP 0-9-1, AMQP 1.0, STOMP, Kafka, AWS, GCP Pub/Sub) are disabled by default. Each opens a new network port and must be explicitly enabled. Enable them with environment variables:

ConnectorEnv varPorts opened
MQTTCONNECTORSMQTT_ENABLE=true1883 / 8883 / 8083
AMQP 0-9-1 (RabbitMQ)CONNECTORS_AMQP_ENABLE=true5672 / 5671
AMQP 1.0CONNECTORS_AMQP10_ENABLE=true5672 / 5671 (shared mux)
STOMPCONNECTORS_STOMP_ENABLE=true61613 / 61614
KafkaCONNECTORS_KAFKA_ENABLE=true9092 / 9093
AWS (SQS & SNS)CONNECTORS_AWS_ENABLE=true4566
GCP Pub/SubCONNECTORS_GCP_ENABLE=true8085

Example — start KubeMQ with MQTT and the AWS connector enabled:

docker run -d \  --name kubemq \  -p 50000:50000 \  -p 9090:9090 \  -p 8080:8080 \  -p 1883:1883 \  -p 4566:4566 \  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \  -e CONNECTORSMQTT_ENABLE=true \  -e CONNECTORS_AWS_ENABLE=true \  europe-docker.pkg.dev/kubemq/images/kubemq:next

Env var spelling matters. The MQTT enable variable is CONNECTORSMQTT_ENABLE — no underscore between CONNECTORS and MQTT. Other connectors use an underscore: CONNECTORS_AMQP_ENABLE, CONNECTORS_STOMP_ENABLE, etc. See the connectors reference for all variable names.

Kafka single-node (Docker)

KubeMQ can expose a Kafka wire-protocol endpoint for single-node Docker development. Kafka runs on the next storage engine — which is auto-selected with zero configuration on a fresh store when the Kafka connector is enabled. You do not set the engine first; see Storage Engines for the full selection rules. Enable Kafka with CONNECTORS_KAFKA_ENABLE=true.

User-defined network

Docker's default bridge network has no DNS, so a Kafka client resolving the advertised container name will not be able to connect there. Create a user-defined network first, then attach KubeMQ to it with a stable --hostname:

Terminal
docker network create mynet

docker run -d \
  --network mynet \
  --name kubemq \
  --hostname kubemq \
  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \
  -e CONNECTORS_KAFKA_ENABLE=true \
  europe-docker.pkg.dev/kubemq/images/kubemq:next

Other containers attached to mynet reach Kafka at kubemq:9092.

Port-mapped host access

To connect from a Kafka client running on the host (outside Docker), advertise localhost and publish the Kafka port. The published host port must equal CONNECTORS_KAFKA_PORT (9092 by default):

docker run -d \  --name kubemq \  -p 9092:9092 \  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \  -e CONNECTORS_KAFKA_ENABLE=true \  -e CONNECTORS_KAFKA_ADVERTISED_HOST=localhost \  europe-docker.pkg.dev/kubemq/images/kubemq:next

A Kafka client on the host can now connect at localhost:9092.

Persistent volume

Give the container a stable --name/--hostname so the advertised name and the store's host-subdir stay stable across restarts, and mount a volume for /store:

Terminal
docker run -d \
  --name kubemq \
  --hostname kubemq \
  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \
  -e CONNECTORS_KAFKA_ENABLE=true \
  -v kubemq-kafka-data:/kubemq/store \
  europe-docker.pkg.dev/kubemq/images/kubemq:next

The user-defined-network and port-mapped-host recipes above are mutually exclusive per deployment. A single advertised endpoint means you pick either user-defined-network reachability or port-mapped host reachability — not both. See the Kafka connector overview and the Kafka settings reference for the full set of options (TLS port, SASL mechanisms, OAUTHBEARER, and more).

Persistence

By default, KubeMQ stores data inside the container at /store. This data is lost when the container is removed. To persist data across container restarts, mount a volume.

Named volume

docker run -d \  --name kubemq \  -p 50000:50000 \  -p 9090:9090 \  -p 8080:8080 \  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \  --hostname kubemq \  -v kubemq-data:/kubemq/store \  europe-docker.pkg.dev/kubemq/images/kubemq:next

Bind mount

Mount a host directory for easier access to the stored data:

docker run -d \  --name kubemq \  -p 50000:50000 \  -p 9090:9090 \  -p 8080:8080 \  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \  --hostname kubemq \  -v $(pwd)/kubemq-store:/kubemq/store \  europe-docker.pkg.dev/kubemq/images/kubemq:next

Persistence is required for Events Store and Queues patterns. Events (fire-and-forget) and RPC patterns do not require persistence, but the store is still used for internal metadata.

Health checks

KubeMQ exposes health endpoints on the API port:

Terminal
# Liveness check — is the process running?
curl http://localhost:8080/health

# Readiness check — is the broker ready to accept traffic?
curl http://localhost:8080/ready

Add a Docker health check to your docker run command:

Terminal
docker run -d \
  --name kubemq \
  -p 50000:50000 \
  -p 9090:9090 \
  -p 8080:8080 \
  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \
  --health-cmd="curl -f http://localhost:8080/health || exit 1" \
  --health-interval=10s \
  --health-timeout=5s \
  --health-retries=3 \
  europe-docker.pkg.dev/kubemq/images/kubemq:next

Upgrade, rollback & backup

KubeMQ ships on the mandatory :next tag — there's no version number to bump. "Upgrading" means re-pulling :next and recreating the container underneath the same name; "rolling back" means restarting from an image you deliberately kept on disk, not from a pinned digest. :next is the only supported channel — see the Helm image-tag policy for why pinning by digest or semver isn't the model.

Upgrade

Re-pull the image and recreate the container:

Terminal
docker pull europe-docker.pkg.dev/kubemq/images/kubemq:next
docker stop kubemq
docker rm kubemq

Then start it again with the same command you used originally (same name, same volume) — Docker resolves :next to the image you just pulled:

docker run -d \  --name kubemq \  -p 50000:50000 \  -p 9090:9090 \  -p 8080:8080 \  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \  --hostname kubemq \  -v kubemq-data:/kubemq/store \  europe-docker.pkg.dev/kubemq/images/kubemq:next

Roll back

Because :next is a moving tag, "rolling back" means restarting from a local image you retained before upgrading — not re-pulling an older digest. Do one of these before you upgrade:

Terminal
# Option A — tag the currently-running image under a name you control
docker tag europe-docker.pkg.dev/kubemq/images/kubemq:next kubemq-known-good

# Option B — or just record its image ID
docker inspect --format='{{.Image}}' kubemq

If the upgrade goes wrong, stop and remove the new container, then start a container from the retained local image (or ID) instead of :next:

Terminal
docker stop kubemq
docker rm kubemq
docker run -d \
  --name kubemq \
  --hostname kubemq \
  -p 50000:50000 \
  -p 9090:9090 \
  -p 8080:8080 \
  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \
  -v kubemq-data:/kubemq/store \
  kubemq-known-good

This is local image retention, not registry pinning. :next stays the only image reference you pull from the registry — the rollback target lives only on this host, which is why you must tag or record it before you re-pull.

Back up the store

The kubemq-data volume — mounted at /kubemq/store in the server container — holds everything Events Store and Queues persist. Back it up with a throwaway container that mounts the same volume (the path inside the throwaway container is arbitrary):

Terminal
docker run --rm -v kubemq-data:/store -v "$(pwd)":/backup alpine \
  tar czf /backup/kubemq-store-backup.tar.gz -C /store .

Restore it the same way, in reverse, onto a fresh volume before starting KubeMQ:

Terminal
docker run --rm -v kubemq-data:/store -v "$(pwd)":/backup alpine \
  sh -c "cd /store && tar xzf /backup/kubemq-store-backup.tar.gz"

Was this page helpful?

On this page