Docker Compose deployment#

The bundled deploy/docker/docker-compose.yml is the canonical reference shape for a Strata stack on one host. Bare docker compose up -d brings up the TiKV-default 2-replica lab (PD + TiKV + ceph + ceph-b + strata-a + strata-b + nginx LB + prometheus + grafana). The Cassandra-backed regression lab lives under --profile cassandra so an operator can make up-cassandra to validate the Cassandra meta backend side by side.

The compose file itself is the source of truth. When it changes, this page may lag by one PR; cross-check ports + env before depending on them.

Prerequisites#

  • Docker Engine ≥24 (or Docker Desktop ≥4.20). macOS via Lima also works (DOCKER_HOST=unix:///Users/.../.lima/.../sock/docker.sock).
  • ≥4 vCPU + 8 GiB free RSS for the full default stack (PD + TiKV + two RADOS clusters + two gateway replicas + Prometheus + Grafana).
  • make (and the Makefile targets the compose file from the repo root).

Install#

The repo’s Makefile wraps the canonical bring-up flow:

make up        # docker compose up -d (TiKV-default lab)
make wait-tikv && make wait-ceph && make wait-strata-lab

make dev runs the same sequence plus a tail of gateway logs — that is the convenience target documented in Get Started.

For the Cassandra-backed regression lab:

make up-cassandra        # docker compose --profile cassandra up -d
make wait-cassandra && make wait-ceph

For tracing (OTel collector + Jaeger UI on :16686):

docker compose --profile tracing up -d otel-collector jaeger
# then set OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318 on the gateway

Profiles compose: docker compose --profile cassandra --profile tracing up -d brings up the bare default + Cassandra-backed gateway + OTel stack in one shot.

Configure#

Service map#

ServiceImageProfileHost portContainer portRole
pdpingcap/pd:v8.5.0default23792379TiKV placement driver (single-node, lab only).
tikvpingcap/tikv:v8.5.0default2016020160TiKV storage node (single-node, lab only).
cephstrata-ceph:localdefaultRADOS data backend default.
ceph-bstrata-ceph:localdefaultSecond RADOS cluster cephb — always on so multi-cluster behaviour is exercisable out of the box.
strata-astrata:cephdefault100019000First TiKV-backed replica. Mounts /etc/ceph-a + /etc/ceph-b. Default workers gc,lifecycle,rebalance.
strata-bstrata:cephdefault100029000Second TiKV-backed replica. Mirrors strata-a; shares the strata-jwt-shared volume so session JWTs validate across replicas.
strata-lb-nginxnginx:1.27-alpinedefault999980LB fronting strata-a + strata-b (round-robin, streaming-friendly).
cassandracassandra:5.0cassandra90429042Cassandra metadata backend (regression lab).
strata-cassandrastrata:cephcassandra99989000Cassandra-backed gateway. Mounts both RADOS clusters.
webhook-trapmendhak/http-https-echo:34webhook-trap8080JSON echo target for the notify worker.
prometheusprom/prometheus:v2.54.1default90909090Scrapes gateway + worker metrics.
grafanagrafana/grafana:11.2.0default30003000Dashboard provisioned from deploy/grafana/.
otel-collectorotel/opentelemetry-collector-contrib:0.110.0tracing4317, 43184317, 4318OTLP collector — fans incoming spans to Jaeger.
jaegerjaegertracing/all-in-one:1.62tracing16686, 1425016686, 14250All-in-one Jaeger backend + UI.

The default docker compose up -d brings up nine services (pd + tikv + ceph + ceph-b + strata-a + strata-b + strata-lb-nginx + prometheus + grafana). Every profile-gated service stays silent until requested.

Profiles#

ProfileWhat it addsBring-up
(default)TiKV-default 2-replica lab + Prometheus + Grafanamake up / make up-all.
cassandraCassandra + strata-cassandra (host :9998)make up-cassandra.
webhook-trapJSON-echo target for the notify workerdocker compose --profile webhook-trap up -d webhook-trap.
tracingOTel collector + Jaegerdocker compose --profile tracing up -d otel-collector jaeger.

Env vars (top knobs)#

The runtime config is a TOML file mounted at /etc/strata/strata.toml (see deploy/strata.toml). Env vars override the file. Full table at Reference — environment variables.

VariableDefault in composePurpose
STRATA_CONFIG_FILE/etc/strata/strata.tomlPath to the TOML config.
STRATA_WORKERSgc,lifecycle,rebalanceComma-separated worker names.
STRATA_AUTH_MODEoptionaloff, optional, required.
STRATA_STATIC_CREDENTIALSadmin:adminpass:owner<access>:<secret>:<role> triples.
STRATA_META_BACKENDtikv (default) / cassandra (profile)Picks the metadata backend at startup.
STRATA_TIKV_PD_ENDPOINTSpd:2379TiKV PD endpoints (comma-separated).
STRATA_RADOS_CLUSTERSdefault:...,cephb:...Multi-cluster RADOS bindings.
STRATA_NODE_IDper replicaIdentifies replica in heartbeat + leader-election rows.
STRATA_GC_SHARDSunset → 1Phase-2 GC fan-out shard count. Set to N when running N replicas.
STRATA_NOTIFY_TARGETSunsetComma-separated target URLs for the notify worker.
STRATA_PROMETHEUS_URLhttp://prometheus:9090Where the embedded console queries metrics.
OTEL_EXPORTER_OTLP_ENDPOINTunsetOTLP/HTTP endpoint.

Volumes + mounts#

The compose file uses named volumes for state so docker compose down doesn’t lose data, and bind-mounts for config so edits take effect on next up.

Volume / mountUsed byPurpose
strata-cassandra-datacassandra/var/lib/cassandra.
strata-ceph-etcceph (rw), strata replicas (ro)/etc/ceph-a — config + keyring for cluster default.
strata-cephb-etcceph-b (rw), strata replicas (ro)/etc/ceph-b — config + keyring for cluster cephb.
strata-ceph-dataceph/var/lib/ceph — RADOS object data.
strata-cephb-dataceph-b/var/lib/ceph — second cluster’s object data.
strata-pd-datapd/data — PD raft log + region metadata.
strata-tikv-datatikv/data — TiKV RocksDB.
strata-prometheus-dataprometheus/prometheus — TSDB.
strata-grafana-datagrafana/var/lib/grafana — dashboards + sessions.
strata-jwt-sharedstrata-a / strata-b/etc/strata/jwt-shared — shared JWT secret bootstrap (file-based, O_EXCL).
../strata.toml (host)every strata serviceRead-only TOML config.
../prometheus/prometheus.yml (host)prometheusScrape config.
../grafana/... (host)grafanaProvisioned data source + dashboard.
../nginx/strata-lab.conf (host)strata-lb-nginxLB config (round-robin upstream).
../otel/collector-config.yaml (host)otel-collectorOTLP collector config.

Tear down + drop state: make down (removes containers across every known profile; named volumes persist). docker compose -f deploy/docker/docker-compose.yml down -v nukes the volumes too.

Verify#

curl http://127.0.0.1:9999/healthz   # nginx LB → strata-a or strata-b
curl http://127.0.0.1:9999/readyz    # both replicas + RADOS + TiKV
curl http://127.0.0.1:10001/readyz   # strata-a direct
curl http://127.0.0.1:10002/readyz   # strata-b direct
aws --endpoint-url http://127.0.0.1:9999 --no-sign-request s3 ls

The operator console: http://127.0.0.1:9999/console/ (trailing slash). Prometheus UI: :9090. Grafana: :3000 (admin/adminpass). Jaeger (tracing profile): :16686.

Monitor#

  • Gateway metrics: Prometheus auto-scrapes strata-a:9000/metrics and strata-b:9000/metrics. The provisioned Grafana dashboard surfaces request rate, GC backlog, replication lag, worker panic counters. See Best Practices — monitoring.
  • Traces: the tracing profile spins an OTel collector + Jaeger all-in-one. Set OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318 on the gateway containers and inspect spans in the Jaeger UI.
  • Logs: JSON to stdout; docker compose logs -f strata-a strata-b for live tail. Each line carries request_id + node_id.

Troubleshoot#

  • make up hangs on wait-tikv. PD took longer than the timeout to elect a leader. docker compose logs pd should show PD leader within ~30 s; if not, restart PD.
  • wait-strata-lab fails. Either RADOS isn’t ready (run make wait-ceph) or the gateway is crash-looping (check docker compose logs strata-a).
  • aws-cli against :9999 returns 404 on the wrong bucket. Path-style URLs route by /<bucket>/<key>. For virtual-hosted-style, set STRATA_VHOST_PATTERN=*.s3.local and use --endpoint-url http://bucket.s3.local:9999.
  • JWT-bootstrap clash: the strata-jwt-shared volume is shared between strata-a + strata-b. If you start strata-cassandra on top, it joins the same volume — session JWTs validate across all three replicas.
  • Cassandra profile won’t reach strata-cassandra:9998. Either Cassandra isn’t ready (make wait-cassandra) or you forgot the --profile cassandra flag on docker compose up.

Production checklist#

For any compose-managed deployment that survives past the lab phase:

  • Pin every image tag to a SHA, not the latest / vN.Y.Z mutable form.
  • Replace STRATA_AUTH_MODE=optional with required; rotate STRATA_STATIC_CREDENTIALS out of the host env into a secret store + STRATA_CONFIG_FILE.
  • Move cassandra / pd / tikv / ceph to dedicated hosts — bundled-on-the-same-box is for labs only. PD ≥3 + TiKV ≥3 for raft majority in production.
  • Configure backups for every data-bearing volume — see Operate — backup & restore.
  • Wire Prometheus alertmanager + log shipping (the bundled compose ships scrape + dashboard, not alerts).
  • Front the gateway with a real LB if you run the bare-default 2-replica shape outside the lab (the bundled nginx is unauthenticated + no TLS).
  • Size STRATA_OTEL_RINGBUF_BYTES for expected traffic (default 4 MiB ≈ a few thousand spans). Wire OTLP collector for retention beyond the ring.

Cross-references#