Skip to Content
GuidesDeploying with Docker

Deploying with Docker

v1 status: stub. Full Dockerfile walkthrough TBD. The rantaiclaw repo ships a Dockerfile and docker-compose.yml you can use directly. The default container command is rantaiclaw gateway (ENTRYPOINT rantaiclaw, CMD gateway), exposing port 3000.

Volume you should mount

The image keeps everything under a single $HOME directory — /rantaiclaw-data — set in the Dockerfile (HOME=/rantaiclaw-data, WORKDIR /rantaiclaw-data). Mount one named volume there and every piece of state survives restarts.

Container pathHoldsPersist?
/rantaiclaw-data ($HOME).rantaiclaw/config.toml, workspace/, memory DB, secret store, audit log, installed skills, and the Knowledge Base databaseYes — mount a named volume

The shipped docker-compose.yml does exactly this:

volumes: - rantaiclaw-data:/rantaiclaw-data

Inside the container the config lives at /rantaiclaw-data/.rantaiclaw/config.toml and the workspace at /rantaiclaw-data/workspace — the running user is the non-root 65534:65534, so a named volume avoids host-permission friction.

Health check

healthcheck: test: ["CMD", "rantaiclaw", "status"] interval: 60s timeout: 10s retries: 3 start_period: 10s

The shipped docker-compose.yml uses the lightweight rantaiclaw status rather than the heavier rantaiclaw doctor (which runs full daemon/scheduler/channel diagnostics). For images that include curl, curl -f http://localhost:3000/health is an equivalent target — /health is an always-public gateway route (src/gateway/mod.rs).

Gateway exposure inside Docker

The gateway config keys are host, port, require_pairing, and allow_public_bind, all under [gateway] (defined in src/config/schema.rs). Outside a container the defaults are deliberately locked down: host = "127.0.0.1", allow_public_bind = false, require_pairing = true. The runtime refuses to start if host is a public address (e.g. 0.0.0.0 / [::]) unless a tunnel is configured or allow_public_bind = true is set.

Inside a container that loopback default would make the published port unreachable, so the shipped image sets host = "[::]" and allow_public_bind = true. This is not an open door: require_pairing = true still gates every request, and you control exposure by which host port you publish and to what network.

  • Do not treat allow_public_bind = true in the image as “safe to expose to the internet” — it only relaxes the in-container bind check.
  • Keep require_pairing = true (the default). Every gateway client must pair first.
  • Publish the host port to a trusted network only. For host-only access, bind the published port to loopback (127.0.0.1:3000:3000); for anything wider, front the gateway with a tunnel or reverse proxy.

Common pitfalls

  • Empty channel allowlist. A channel with an empty allowlist is offline, not open (deny-by-default). Run rantaiclaw doctor in CI and fail on any non-OK result to catch a channel that is enabled but unreachable.
  • Forgetting allow_public_bind. If you set host = "0.0.0.0" (or [::]) in [gateway] you must also set allow_public_bind = true, or the gateway refuses to start. Only do this behind pairing plus a trusted network boundary.
  • Landlock kernel support. On Linux the Landlock sandbox compiles automatically (the legacy sandbox-landlock feature flag is now a no-op) and activates at runtime on kernel 5.13+; on older kernels the runtime falls back to allowlist-only enforcement. Pin a base image with kernel 5.13+ for full sandboxing.
Last updated on