The images resolve the whole workspace graph before cargo fetch, so every member manifest has to be in the build context by then, and the copied list had fallen six crates behind the workspace: the backend split added sandbox-local, sandbox-lxd, and sandbox-server, and the cloud frontends added cloud-agent, cloudflare-code, and vercel-agent. rhema-code path-depends on the sandbox backends, so the claw image was the first to break — the fetch died reading the lxd manifest.
106 lines
5.7 KiB
Docker
106 lines
5.7 KiB
Docker
# rhema-claw: the resident forge-watching daemon.
|
|
# Build from the repo root (the context is the repo):
|
|
# docker build -f deploy/docker/claw.Dockerfile .
|
|
|
|
# The builder tag tracks rust-toolchain.toml: the pinned channel is what
|
|
# every commit is tested against. The full image (not -slim) carries the C
|
|
# toolchain rusqlite's bundled SQLite build needs.
|
|
FROM rust:1.98.1 AS builder
|
|
WORKDIR /build
|
|
|
|
# Manifests first: the registry cache this populates survives source edits.
|
|
COPY Cargo.toml Cargo.lock rust-toolchain.toml ./
|
|
COPY crates/rhema-acp/Cargo.toml crates/rhema-acp/Cargo.toml
|
|
COPY crates/rhema-agent-tools/Cargo.toml crates/rhema-agent-tools/Cargo.toml
|
|
COPY crates/rhema-autonomous-agent/Cargo.toml crates/rhema-autonomous-agent/Cargo.toml
|
|
COPY crates/rhema-claw/Cargo.toml crates/rhema-claw/Cargo.toml
|
|
COPY crates/rhema-cloud-agent/Cargo.toml crates/rhema-cloud-agent/Cargo.toml
|
|
COPY crates/rhema-cloudflare-code/Cargo.toml crates/rhema-cloudflare-code/Cargo.toml
|
|
COPY crates/rhema-code/Cargo.toml crates/rhema-code/Cargo.toml
|
|
COPY crates/rhema-coding-agent/Cargo.toml crates/rhema-coding-agent/Cargo.toml
|
|
COPY crates/rhema-config/Cargo.toml crates/rhema-config/Cargo.toml
|
|
COPY crates/rhema-core/Cargo.toml crates/rhema-core/Cargo.toml
|
|
COPY crates/rhema-identity/Cargo.toml crates/rhema-identity/Cargo.toml
|
|
COPY crates/rhema-memory/Cargo.toml crates/rhema-memory/Cargo.toml
|
|
COPY crates/rhema-provider/Cargo.toml crates/rhema-provider/Cargo.toml
|
|
COPY crates/rhema-provider-anthropic/Cargo.toml crates/rhema-provider-anthropic/Cargo.toml
|
|
COPY crates/rhema-provider-copilot/Cargo.toml crates/rhema-provider-copilot/Cargo.toml
|
|
COPY crates/rhema-provider-google/Cargo.toml crates/rhema-provider-google/Cargo.toml
|
|
COPY crates/rhema-provider-llama-cpp/Cargo.toml crates/rhema-provider-llama-cpp/Cargo.toml
|
|
COPY crates/rhema-provider-openai-compatible/Cargo.toml crates/rhema-provider-openai-compatible/Cargo.toml
|
|
COPY crates/rhema-provider-openrouter/Cargo.toml crates/rhema-provider-openrouter/Cargo.toml
|
|
COPY crates/rhema-rsd/Cargo.toml crates/rhema-rsd/Cargo.toml
|
|
COPY crates/rhema-sandbox/Cargo.toml crates/rhema-sandbox/Cargo.toml
|
|
COPY crates/rhema-sandbox-docker/Cargo.toml crates/rhema-sandbox-docker/Cargo.toml
|
|
COPY crates/rhema-sandbox-http/Cargo.toml crates/rhema-sandbox-http/Cargo.toml
|
|
COPY crates/rhema-sandbox-local/Cargo.toml crates/rhema-sandbox-local/Cargo.toml
|
|
COPY crates/rhema-sandbox-lxd/Cargo.toml crates/rhema-sandbox-lxd/Cargo.toml
|
|
COPY crates/rhema-sandbox-server/Cargo.toml crates/rhema-sandbox-server/Cargo.toml
|
|
COPY crates/rhema-sandbox-ssh/Cargo.toml crates/rhema-sandbox-ssh/Cargo.toml
|
|
COPY crates/rhema-subagents/Cargo.toml crates/rhema-subagents/Cargo.toml
|
|
COPY crates/rhema-transcript/Cargo.toml crates/rhema-transcript/Cargo.toml
|
|
COPY crates/rhema-vercel-agent/Cargo.toml crates/rhema-vercel-agent/Cargo.toml
|
|
COPY integrations/rhema-calendar-integration/Cargo.toml integrations/rhema-calendar-integration/Cargo.toml
|
|
COPY integrations/rhema-forge-integration/Cargo.toml integrations/rhema-forge-integration/Cargo.toml
|
|
# rhema-claw path-depends on the tools contract, which lives in its own
|
|
# workspace: the member manifests inherit from that root, so the root
|
|
# rides along with them.
|
|
COPY tools/Cargo.toml tools/Cargo.toml
|
|
COPY tools/contract/Cargo.toml tools/contract/Cargo.toml
|
|
COPY tools/common/Cargo.toml tools/common/Cargo.toml
|
|
COPY tools/notify/Cargo.toml tools/notify/Cargo.toml
|
|
|
|
|
|
# Resolution reads the vendored crossterm (the root manifest path-patches
|
|
# to it) even though the image builds the daemon, which does not link it.
|
|
COPY vendor/ vendor/
|
|
|
|
# Cargo validates explicit target
|
|
# paths at manifest-parse time, so the fetch needs stub files at every
|
|
# declared target path: src/ for every member, plus examples/tests/benches
|
|
# as declared (default path from the target name, or the explicit `path`).
|
|
# The loop drives off the crates/*/ and integrations/*/ globs because
|
|
# neither glob's */src matches anything until the stub exists — an
|
|
# unmatched glob would hand mkdir a literal path. The real sources land
|
|
# below. (The awk program must stay on one line: a Dockerfile line not
|
|
# ending in a backslash ends the RUN.)
|
|
RUN for crate in crates/*/ integrations/*/ tools/*/; do \
|
|
mkdir -p "$crate/src"; \
|
|
touch "$crate/src/lib.rs" "$crate/src/main.rs"; \
|
|
awk -F'"' '/^\[/ { d = ""; p = 0; if ($0 == "[[example]]") { d = "examples" } else if ($0 == "[[test]]") { d = "tests" } else if ($0 == "[[bench]]") { d = "benches" }; next } d == "" { next } /^name = / && p == 0 { print d "/" $2 ".rs" } /^path = / { p = 1; print $2 }' "$crate/Cargo.toml" \
|
|
| while IFS= read -r target; do \
|
|
mkdir -p "$crate$(dirname "$target")"; \
|
|
touch "$crate$target"; \
|
|
done; \
|
|
done \
|
|
&& cargo fetch
|
|
|
|
# Sources. target/ and .git never land here: the repo-root .dockerignore
|
|
# keeps them out of the context.
|
|
COPY . .
|
|
RUN cargo build --release -p rhema-claw
|
|
|
|
FROM debian:stable-slim
|
|
|
|
# bash and git are load-bearing, not conveniences: the coding agent shells
|
|
# out via `bash -c` and clones/fetches in its per-thread workspaces.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends bash git ca-certificates \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Numeric USER: Kubernetes cannot verify runAsNonRoot against a name.
|
|
RUN useradd --uid 1000 --user-group --create-home claw \
|
|
&& install -d -o 1000 -g 1000 /config /data
|
|
|
|
COPY --from=builder /build/target/release/rhema-claw /usr/local/bin/rhema-claw
|
|
|
|
# The chart passes --config /config/claw.yaml (the ConfigMap mount) and
|
|
# mounts the state PVC at /data; these defaults serve a bare `docker run`.
|
|
ENV XDG_CONFIG_HOME=/config \
|
|
XDG_STATE_HOME=/data/state
|
|
VOLUME /data
|
|
EXPOSE 7799
|
|
|
|
USER 1000:1000
|
|
ENTRYPOINT ["/usr/local/bin/rhema-claw"]
|