# Docker (single-node) (/docs/configure/docker)



Docker single-node **is** the standalone KubeMQ server, containerized. One container
runs the full server: every interface, every connector, the persistent store, and the
embedded messaging engine. There is no separate "bare-binary" target — the container
*is* the binary. This guide hosts the complete, runnable Docker configs; the
[reference](/docs/configure/reference) pages show per-setting snippets and link back
here.

**Install KubeMQ first** → [Docker install](/docs/deploy/docker). This
page covers how to *configure* a single node, not how to install one.

| Port    | Interface        | Purpose                                                                    |
| ------- | ---------------- | -------------------------------------------------------------------------- |
| `50000` | gRPC             | Primary SDK transport.                                                     |
| `9090`  | REST / WebSocket | REST API, WebSocket, and the shared HTTP server (MCP · A2A · CloudEvents). |
| `8080`  | API / Dashboard  | Web dashboard, management API, health probes, and metrics.                 |

The store is bind-mounted to `/store` inside the container — the path the server writes
to by default. Persistence is required for the **Events Store** and **Queues** patterns.

## Three ways to supply config [#three-ways-to-supply-config]

Every setting has a documented default, so a server runs with no overrides at all. To change
a setting you have three delivery methods, in order of how much you are configuring:

### Per-field environment variables [#per-field-environment-variables]

Pass each setting as `-e GROUP_FIELD=value`. The env var is the `config.yaml` key
snake-cased, dotless, and uppercased — `store.maxretention` becomes `STORE_MAX_RETENTION`.
This is the lightest method, best for a handful of overrides:

<RunKubeMQ env="{ LOG_LEVEL: '1', STORE_MAX_RETENTION: '2880', CONNECTORSCE_ENABLE: 'false' }" />

<Callout type="warn">
  **The connector acronym variables drop the underscore.*&#x2A; The CloudEvents enable variable
  is &#x2A;*`CONNECTORSCE_ENABLE`** (no underscore between `CONNECTORS` and `CE`). The form
  `CONNECTORS_CE_ENABLE` (with the underscore) does **not** bind — the server starts,
  accepts the variable without error, and silently ignores it. The same holds for
  `CONNECTORSMCP_*` and `CONNECTORSMQTT_*`, while the Title-case connectors keep the
  underscore (`CONNECTORS_AMQP_*`, `CONNECTORS_STOMP_*`, `CONNECTORS_AWS_*`), and A2A splits
  to `CONNECTORSA2_A_*`. The full rule is in
  [the reference legend](/docs/configure/reference).
</Callout>

### A mounted config.yaml [#a-mounted-configyaml]

Once you are setting more than a few fields, keep them in a `config.yaml` and mount it into
the container. The server auto-detects YAML or TOML; point it at the file with the
`--config` flag (the server's start command takes arguments after the image name):

```yaml title="config.yaml"
# Replace with your license key
key: YOUR_LICENSE_KEY
log:
  level: 1
store:
  storepath: /store
  maxretention: 2880
connectors:
  grpc:
    enable: true
    port: "50000"
  rest:
    enable: true
    port: "9090"
  ce:
    enable: false
api:
  port: "8080"
```

Mount the file and select it with `--config`:

```bash title="Terminal"
docker run -d \
  --name kubemq \
  -p 50000:50000 \
  -p 9090:9090 \
  -p 8080:8080 \
  -v "$(pwd)/kubemq-store:/store" \
  -v "$(pwd)/config.yaml:/kubemq/config.yaml:ro" \
  europe-docker.pkg.dev/kubemq/images/kubemq:next \
  --config /kubemq/config.yaml
```

<Callout type="warn">
  **`enable` is the Docker toggle — but the default differs by family.** The interfaces and
  the HTTP-family connectors (gRPC, REST, API, MCP, A2A, CloudEvents) ship **on by default**;
  the wire-protocol connectors (MQTT, AMQP, STOMP, Kafka, AWS, GCP) are **opt-in** and ship
  **off**. On Docker you flip either with `enable: true | false` (env `..._ENABLE`) — turn an
  always-on interface **off** with `enable: false`, or turn a wire connector **on** with
  `enable: true`. The Helm/CRD surface splits the two: the always-on interfaces use an opt-out
  `disabled: true`, while the wire connectors use an opt-in `enabled: true` (see
  [Kubernetes](/docs/configure/kubernetes)). Same toggles, inverted boolean.
</Callout>

### The CONFIG environment variable [#the-config-environment-variable]

When mounting a file is awkward — orchestrators that inject env vars, CI runners, secret
managers — supply the **whole** config inline through the `CONFIG` environment variable.
The server writes the value to a file and loads it, exactly as if you had passed
`--config`:

```bash title="Terminal"
docker run -d \
  --name kubemq \
  -p 50000:50000 \
  -p 9090:9090 \
  -p 8080:8080 \
  -v "$(pwd)/kubemq-store:/store" \
  -e CONFIG="$(cat config.yaml)" \
  europe-docker.pkg.dev/kubemq/images/kubemq:next
```

`CONFIG` also accepts a **base64-encoded** payload, which avoids newline and quoting
issues when the value passes through a secret store or a templating layer:

```bash title="Terminal"
docker run -d \
  --name kubemq \
  -p 50000:50000 \
  -p 9090:9090 \
  -p 8080:8080 \
  -v "$(pwd)/kubemq-store:/store" \
  -e CONFIG="$(base64 < config.yaml)" \
  europe-docker.pkg.dev/kubemq/images/kubemq:next
```

## docker-compose [#docker-compose]

The same single node as a `docker-compose.yaml`, combining a mounted `config.yaml` with a
couple of per-field environment overrides:

```yaml title="docker-compose.yaml"
services:
  kubemq:
    image: europe-docker.pkg.dev/kubemq/images/kubemq:next
    container_name: kubemq
    command: ["--config", "/kubemq/config.yaml"]
    ports:
      - "50000:50000"  # gRPC
      - "9090:9090"    # REST / WebSocket
      - "8080:8080"    # API / Dashboard
    environment:
      - KUBEMQ_TOKEN=${KUBEMQ_TOKEN:-}
      - LOG_LEVEL=1
    volumes:
      - kubemq-store:/store
      - ./config.yaml:/kubemq/config.yaml:ro
    restart: unless-stopped

volumes:
  kubemq-store:
```

Start it:

```bash title="Terminal"
docker compose up -d
```

To supply the config inline instead of mounting a file, drop the `command` and
`config.yaml` volume and set `CONFIG` (or `CONFIG` as base64) in the `environment` block.

## Configure by domain [#configure-by-domain]

Every setting in the configs above is documented in the reference, grouped by domain. Each
page lists the `config.yaml` key, the environment variable, the type, the default, and the
valid values.

<Cards>
  <Card title="Core & Licensing" href="/docs/configure/reference/core" description="License key, log level, and host/server identity." />

  <Card title="Interfaces" href="/docs/configure/reference/interfaces" description="gRPC, REST/WebSocket, the management API, and the shared HTTP server with CORS." />

  <Card title="Connectors" href="/docs/configure/reference/connectors" description="MCP, A2A (agents), CloudEvents, MQTT, AMQP 0.9.1, AMQP 1.0, STOMP, Kafka, AWS, and GCP Pub/Sub." />

  <Card title="Storage & Queues" href="/docs/configure/reference/storage-queues" description="Persistent store limits and retention plus queue delivery defaults and ceilings." />

  <Card title="Security" href="/docs/configure/reference/security" description="JWT and OIDC authentication, policy-based authorization, and TLS/mTLS." />

  <Card title="Observability" href="/docs/configure/reference/observability" description="OpenTelemetry traces and metrics, audit logging, and notifications." />

  <Card title="Deployment & High Availability" href="/docs/configure/reference/deployment" description="Kubernetes packaging — image, volume, resources, health, scheduling, Service exposure — plus replicas and standalone mode." />

  <Card title="Advanced" href="/docs/configure/reference/advanced" description="Message-broker engine, runtime tuning, and routing — config.yaml-only advanced knobs." />
</Cards>

## Verify [#verify]

Confirm the node is up. Open the dashboard at
`http://localhost:8080`, then check the container logs:

```bash title="Terminal"
docker logs kubemq
```

A healthy start logs each interface binding to its port. The health and readiness probes
on the API port confirm the server is accepting traffic:

```bash title="Terminal"
curl http://localhost:8080/health
curl http://localhost:8080/ready
```

## Related [#related]

* [Kubernetes (Helm)](/docs/configure/kubernetes) — the production target with replicas and `Service` exposure.
* [Configuration overview](/docs/configure) — the two targets and the config model.
* [Configuration reference](/docs/configure/reference) — every setting, grouped by domain.
