Docker container
This guide runs a plain, non-secured Zaris cluster as Docker containers: four nodes from a single image, all sharing one config file, discovering each other by service name. It corresponds to the docker/ directory in the Zaris repository and uses the attach deployment model.
Use this for local development and evaluation. For a secured cluster with mutual TLS and token authentication, see Docker Compose (secured); for orchestration, see Kubernetes.
How the node image works
Every node runs the same image, clustron-zaris-node:local, built from docker/Dockerfile.node. The image publishes Clustron.Zaris.Host onto the .NET 8 ASP.NET runtime and starts it with a fixed entrypoint that reads a mounted config file:
dotnet Clustron.Zaris.Host.dll --ConfigPath /config/clustron.json
Three facts define how a node behaves in a container:
- One image, one config. Every container mounts the same
config/clustron.jsonat/config/clustron.json(read-only). The config lists all nodes undernodes[], each with itsid,host,clusterPort(7811), andclientPort(7861). CLUSTRON_NODE_IDgives each container its identity. A node learns which of the configured nodes it is from theCLUSTRON_NODE_IDenvironment variable, set per service and validated againstnodes[]. This is the entire per-container identity mechanism.- Peers find each other by service name. The
hostvalues in the config are the Compose service names (zaris-n0..zaris-n3). Docker's built-in DNS resolves them on the shared bridge network — no external discovery service is needed.
The store is in-memory, so no data volume is required. Each container has its own network namespace, so all nodes share the same ports: the client port 7861 (where clients connect) and the cluster port 7811 (intra-cluster peer traffic).
Prerequisites
Confirm the following before you start:
- Docker and Docker Compose installed and running (Docker Desktop on Windows works).
- The Zaris repository checked out locally. The
docker composecommands below run from itsdocker/directory.
Build the node image
The Dockerfile's build context is the repository root, so build from there and point at the Dockerfile under docker/. From the repository root, run:
docker build -t clustron-zaris-node:local -f docker/Dockerfile.node .
Compose also builds the image on demand (--build), so this explicit step is optional but useful for confirming the image builds cleanly.
Run the plain node-only cluster
The docker-compose.yml file defines four node services — zaris-n0 through zaris-n3 — on a bridge network named zaris. Each service sets its own CLUSTRON_NODE_ID, mounts the shared config, and publishes its client port to a distinct host port in the 1786x range so it does not clash with a native Windows cluster on 7861.
-
From the
docker/directory, build the image and start the four nodes:docker compose up --build -d -
Watch the nodes form a cluster, and confirm they report healthy once their client ports are listening:
docker compose logs -f zaris-n0
docker compose ps -
When you are done, tear the cluster down:
docker compose down
This stack is node-only — it runs the store engine with no Management Service and no Web Console. Each node's client port maps to the host as follows:
| Service | Container client port | Host port |
|---|---|---|
zaris-n0 | 7861 | 17861 |
zaris-n1 | 7861 | 17862 |
zaris-n2 | 7861 | 17863 |
zaris-n3 | 7861 | 17864 |
The cluster port 7811 stays internal to the zaris network.
The cluster advertises peer endpoints by their in-network service names, so the most reliable way to use the store is from inside the zaris network. A host-mapped client port (localhost:17861) reaches one node directly, but a host-side client may be handed an in-network peer address it cannot resolve. Run clients as containers attached to the zaris network, or use the manager stack below.
Run with a manager and Web Console (attach)
To get a Web Console and a single, coherent cluster view, use the attach stack instead. docker-compose.attach.yml adds one Management Service container (clustron-zaris-machine:local) that runs with ZARIS_MGMT_MODE=attach: it observes the four orchestrator-run nodes and adopts them with Register-ZrStore — it never forks a node.
The up.ps1 script wraps this end to end — it resets any previous stack, builds, starts the four nodes plus the attach manager, waits for health, and registers the running cluster as a store.
-
From the
docker/directory, bring up the attach stack and adopt the cluster:./up.ps1To reuse the existing image without rebuilding, add
-NoBuild; to keep existing data volumes, add-KeepData. -
Alternatively, run Compose directly and register the store yourself:
docker compose -f docker-compose.attach.yml up --build -d
When the stack is up, the control plane is published to the host:
- Web Console —
http://localhost:18101 - Management API —
http://localhost:17801 - Nodes (client) —
localhost:17861..17864
Drive the cluster from the Console, or from the AdminShell inside the manager container:
docker exec -it zaris-manager pwsh
# then: Get-ZrStore, Get-ZrNode, ...
Tear the attach stack down with ./down.ps1, or docker compose -f docker-compose.attach.yml down -v.
Scale the node count
Node membership is declared in the config, so scaling means editing two files in step. To change the node count:
- Add or remove entries in
nodes[]inconfig/clustron.json, keeping each node'sid,host,clusterPort, andclientPortconsistent. - Add or remove matching services in the Compose file, each with its own
CLUSTRON_NODE_IDthat references anodes[]entry. - Recreate the stack so the containers pick up the new config.
Next steps
- Secure the containerized cluster → Docker Compose (secured).
- Orchestrate the same image on Kubernetes → Kubernetes.
- Understand the deployment models → Deployment overview.