Skip to Content

Docker

topics is published as a single container image to the GitHub Container Registry at ghcr.io/slopus/topics. The image is multi-arch (linux/amd64 and linux/arm64), runs as a non-root user, and stores all durable state in a /data volume. This page covers running it and how releases are cut.

Pull and run

The image binds 0.0.0.0:4000 inside the container. Because the server refuses to start on a non-loopback bind with no API keys — it would be an open, unauthenticated event store — you must pass either TOPICS_API_KEYS (any real deployment) or, for local/dev only, TOPICS_ALLOW_INSECURE_NO_AUTH=1.

# Production: bearer auth on. Clients send `Authorization: Bearer <key>`. docker run --rm \ -p 4000:4000 \ -v topics-data:/data \ -e TOPICS_API_KEYS=replace-with-a-real-secret \ ghcr.io/slopus/topics:latest
# → check it's up (health is always 200 once serving) curl -fsS http://127.0.0.1:4000/v0/health

TOPICS_ALLOW_INSECURE_NO_AUTH=1 exists only so you can run the 0.0.0.0-binding image locally without keys. On anything reachable from a network, set TOPICS_API_KEYS instead. See Security.

What each flag does:

FlagPurpose
-p 4000:4000Maps the container’s listen port (EXPOSE 4000) to the host.
-v topics-data:/dataA named volume holding the WAL, segments, and snapshots. TOPICS_DATA_DIR defaults to /data in the image.
-e TOPICS_API_KEYS=...Comma-separated bearer keys (production).
-e TOPICS_ALLOW_INSECURE_NO_AUTH=1Permits a keyless start on the 0.0.0.0 bind (local/dev only).

The /data volume

The image sets TOPICS_DATA_DIR=/data and declares /data as a VOLUME. That directory holds everything durable — the WAL, sealed segment files, and snapshots. Reuse the same volume across restarts to preserve durable state; on the next start the server replays the WAL from /data and recovers acknowledged writes. A fresh empty volume is a clean first start.

# Inspect the durable state directory inside a running container. docker exec -it <container> ls -la /data

For the on-disk layout and optional hot→cold relocation (TOPICS_COLD_DIR), see Storage & Tiering. For every tunable, see Configuration.

Image internals

The image is built from a multi-stage Dockerfile and is deliberately minimal:

  • Non-root. The server runs as a dedicated system user (uid 10001) that owns /data.
  • Slim runtime. A debian:bookworm-slim base with only ca-certificates and curl (the latter for the health check). Only the topics server binary is shipped — the topics-probe test/bench CLI is excluded to keep the image lean.
  • Defaults baked in. TOPICS_HOST=0.0.0.0, TOPICS_PORT=4000, TOPICS_DATA_DIR=/data.
  • EXPOSE 4000 for the listen port.
  • HEALTHCHECK. A built-in liveness probe runs curl -fsS http://127.0.0.1:$TOPICS_PORT/v0/health every 30s (5s timeout, 10s start period, 3 retries). /v0/health is always 200 once the process is serving.

The container HEALTHCHECK hits /v0/health (liveness). For orchestrator readiness — gating traffic until WAL replay completes — use /v0/ready, which returns 503 during recovery and 200 once ready. See Running topics and Observability.

Release flow

Releases are tag-driven, built by GitHub Actions, and published to GHCR.

  1. Make sure main is green (CI runs build + test + clippy on every push and PR).

  2. Tag the commit with a vX.Y.Z version and push the tag:

    git tag v1.2.3 git push origin v1.2.3
  3. The Publish container image workflow triggers on the v* tag, builds the multi-arch image (linux/amd64 + linux/arm64), attaches provenance and SBOM attestations, and pushes it to GHCR under three tags:

    TagExampleMeaning
    :X.Y.Zghcr.io/slopus/topics:1.2.3The exact version.
    :X.Yghcr.io/slopus/topics:1.2The latest patch of a minor line.
    :latestghcr.io/slopus/topics:latestThe newest tagged release.

You can also trigger the workflow manually from the Actions tab (workflow_dispatch); a manual run is tagged with the short commit SHA instead of a version. The workflow uses the built-in GITHUB_TOKEN with packages: write, so no extra secrets are required.

Pin a specific :X.Y.Z (or :X.Y) tag in production for reproducible deploys; reserve :latest for evaluation.

See also

Last updated on