-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Expand file tree
/
Copy pathDockerfile.debian
More file actions
219 lines (203 loc) Β· 10.8 KB
/
Copy pathDockerfile.debian
File metadata and controls
219 lines (203 loc) Β· 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# syntax=docker/dockerfile:1.7-labs
# >>> generated:base-arg-node from dev/ci/container-base-images.toml by `cargo generate installers` - do not edit <<<
ARG ZEROCLAW_BASE_NODE=node:24-bookworm-slim@sha256:6f7b03f7c2c8e2e784dcf9295400527b9b1270fd37b7e9a7285cf83b6951452d
# >>> end generated:base-arg-node <<<
# >>> generated:base-arg-rust-bookworm from dev/ci/container-base-images.toml by `cargo generate installers` - do not edit <<<
ARG ZEROCLAW_BASE_RUST_BOOKWORM=rust:1.96-bookworm@sha256:a339861ae23e9abb272cea45dfafde21760d2ce6577a70f8a926153677902663
# >>> end generated:base-arg-rust-bookworm <<<
# ββ Stage 0: Frontend build βββββββββββββββββββββββββββββββββββββ
FROM ${ZEROCLAW_BASE_NODE} AS web-node
FROM ${ZEROCLAW_BASE_RUST_BOOKWORM} AS web-builder
WORKDIR /app
COPY --from=web-node /usr/local/bin/node /usr/local/bin/node
COPY --from=web-node /usr/local/lib/node_modules /usr/local/lib/node_modules
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install -y \
g++ \
pkg-config \
&& ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
&& ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx \
&& rm -rf /var/lib/apt/lists/*
COPY web/package.json web/package-lock.json web/
RUN cd web && npm ci --ignore-scripts
COPY . .
RUN mkdir -p apps/tauri/src \
&& echo "fn main() {}" > apps/tauri/src/main.rs \
&& echo "fn main() {}" > apps/tauri/build.rs
RUN --mount=type=cache,id=zeroclaw-cargo-registry,target=/usr/local/cargo/registry,sharing=locked \
--mount=type=cache,id=zeroclaw-cargo-git,target=/usr/local/cargo/git,sharing=locked \
--mount=type=cache,id=zeroclaw-web-target,target=/app/target,sharing=locked \
cargo web build
# Dockerfile.debian β Shell-equipped variant of the ZeroClaw container.
#
# The default Dockerfile produces a distroless "release" image with no shell,
# which is ideal for minimal attack surface but prevents the agent from using
# shell-based tools (pwd, ls, git, curl, etc.).
#
# This variant uses debian:bookworm-slim as the runtime base and ships
# essential CLI tools so the agent can operate as a full coding assistant.
#
# Build:
# docker build -f Dockerfile.debian -t zeroclaw:debian .
#
# Or with docker compose:
# docker compose -f docker-compose.yml -f docker-compose.debian.yml up
# ββ Stage 1: Build (match runtime glibc baseline) βββββββββββ
FROM ${ZEROCLAW_BASE_RUST_BOOKWORM} AS builder
WORKDIR /app
# >>> generated:docker-features-arg by `cargo generate installers` - do not edit <<<
ARG ZEROCLAW_CARGO_FLAGS="--no-default-features --features acp-bridge,agent-runtime,channel-acp-server,channel-discord,channel-email,channel-filesystem,channel-lark,channel-matrix,channel-telegram,channel-webhook,gateway,observability-prometheus,schema-export,whatsapp-web"
# >>> end generated:docker-features-arg <<<
# Install build dependencies
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install -y \
pkg-config \
g++ \
&& rm -rf /var/lib/apt/lists/*
# 1. Copy manifests to cache dependencies
COPY Cargo.toml Cargo.lock ./
# Copy every workspace-member manifest in one glob β adding or removing a crate
# no longer requires editing this file. --parents preserves the
# crates/<name>/Cargo.toml directory structure.
COPY --parents crates/*/Cargo.toml ./
# apps/tauri: .dockerignore whitelists only Cargo.toml; src and build.rs are stubbed below.
COPY apps/tauri/Cargo.toml apps/tauri/Cargo.toml
# apps/zerocode: TUI app not shipped in the server image; copy only its manifest
# so Cargo can resolve the workspace, then stub its src/main.rs and build.rs
# below. Its real build.rs reads web/src/contexts/themes.json and would panic in
# this pre-fetch stage, so it is stubbed exactly like apps/tauri.
COPY apps/zerocode/Cargo.toml apps/zerocode/Cargo.toml
# tools/fill-translations and xtask are dev/build tools; copy manifests only so
# Cargo can resolve the workspace, then stub their entry points so the
# dependency pre-fetch step succeeds without building them into the image.
COPY tools/fill-translations/Cargo.toml tools/fill-translations/Cargo.toml
COPY xtask/Cargo.toml xtask/Cargo.toml
# Create dummy targets for all workspace members so manifest parsing succeeds.
# `src/bin/zeroclaw-acp-bridge.rs` is required because the `acp-bridge` feature
# is in the root crate's default set; cargo selects the bin target during the
# pre-fetch build even with only the workspace lib stubbed.
RUN mkdir -p src src/bin benches apps/tauri/src apps/zerocode/src tools/fill-translations/src xtask/src/bin \
&& echo "fn main() {}" > src/main.rs \
&& echo "" > src/lib.rs \
&& echo "fn main() {}" > src/bin/zeroclaw-acp-bridge.rs \
&& echo "fn main() {}" > benches/agent_benchmarks.rs \
&& echo "fn main() {}" > apps/tauri/src/main.rs \
&& echo "fn main() {}" > apps/tauri/build.rs \
&& echo "fn main() {}" > apps/zerocode/src/main.rs \
&& echo "fn main() {}" > apps/zerocode/build.rs \
&& echo "fn main() {}" > tools/fill-translations/src/main.rs \
&& echo "" > xtask/src/lib.rs \
&& echo "fn main() {}" > xtask/src/bin/mdbook.rs \
&& echo "fn main() {}" > xtask/src/bin/fluent.rs \
&& echo "fn main() {}" > xtask/src/bin/web.rs \
&& mkdir -p crates/zeroclaw-hardware/examples \
&& echo "fn main() {}" > crates/zeroclaw-hardware/examples/esp32_sim.rs \
&& for d in crates/*/; do mkdir -p "${d}src" && printf '' > "${d}src/lib.rs"; done
RUN --mount=type=cache,id=zeroclaw-cargo-registry,target=/usr/local/cargo/registry,sharing=locked \
--mount=type=cache,id=zeroclaw-cargo-git,target=/usr/local/cargo/git,sharing=locked \
--mount=type=cache,id=zeroclaw-target,target=/app/target,sharing=locked \
if [ -n "$ZEROCLAW_CARGO_FLAGS" ]; then \
cargo build --release --locked -p zeroclawlabs -p zerocode $ZEROCLAW_CARGO_FLAGS; \
else \
cargo build --release --locked -p zeroclawlabs -p zerocode; \
fi
RUN rm -rf src benches crates xtask tools/fill-translations
# 2. Copy only build-relevant source paths (avoid cache-busting on docs/tests/scripts)
COPY src/ src/
COPY benches/ benches/
COPY crates/ crates/
COPY xtask/ xtask/
COPY tools/fill-translations/ tools/fill-translations/
# apps/zerocode ships in the image; copy its real source. Its build.rs reads the
# dashboard theme registry under web/src/contexts, so that path must be present.
COPY apps/zerocode/ apps/zerocode/
COPY web/src/ web/src/
# locales.toml lives at repo root and is embedded by zeroclaw-runtime via
# include_str!("../../../locales.toml"); the real build needs it present.
COPY locales.toml .
COPY --from=web-builder /app/web/dist web/dist
RUN touch src/main.rs src/lib.rs apps/zerocode/src/main.rs
RUN --mount=type=cache,id=zeroclaw-cargo-registry,target=/usr/local/cargo/registry,sharing=locked \
--mount=type=cache,id=zeroclaw-cargo-git,target=/usr/local/cargo/git,sharing=locked \
--mount=type=cache,id=zeroclaw-target,target=/app/target,sharing=locked \
rm -rf target/release/.fingerprint/zeroclawlabs-* \
target/release/deps/zeroclawlabs-* \
target/release/incremental/zeroclawlabs-* \
target/release/.fingerprint/zeroclaw-* \
target/release/deps/zeroclaw_* \
target/release/incremental/zeroclaw_* \
target/release/.fingerprint/xtask-* \
target/release/deps/xtask-* \
target/release/.fingerprint/fill-translations-* \
target/release/deps/fill_translations-* \
target/release/.fingerprint/zerocode-* \
target/release/deps/zerocode-* \
target/release/incremental/zerocode-* && \
if [ -n "$ZEROCLAW_CARGO_FLAGS" ]; then \
cargo build --release --locked -p zeroclawlabs -p zerocode $ZEROCLAW_CARGO_FLAGS; \
else \
cargo build --release --locked -p zeroclawlabs -p zerocode; \
fi && \
cp target/release/zeroclaw /app/zeroclaw && \
cp target/release/zerocode /app/zerocode && \
strip /app/zeroclaw /app/zerocode
RUN for b in zeroclaw zerocode; do \
size=$(stat -c%s "/app/$b") && \
if [ "$size" -lt 1000000 ]; then echo "ERROR: $b too small (${size} bytes), likely dummy build artifact" && exit 1; fi; \
done
# Prepare runtime directory structure and default config inline (no extra stage).
# The web dashboard bundle is installed in the runtime stage at
# /usr/share/zeroclawlabs/web/dist (outside the documented /zeroclaw-data
# mount point) so a bind mount on /zeroclaw-data cannot shadow it (#6400).
RUN mkdir -p /zeroclaw-data/.zeroclaw /zeroclaw-data/data && \
printf '%s\n' \
'api_key = ""' \
'default_provider = "openrouter"' \
'default_model = "anthropic/claude-sonnet-4-20250514"' \
'default_temperature = 0.7' \
'' \
'[gateway]' \
'port = 42617' \
'host = "[::]"' \
'allow_public_bind = true' \
'web_dist_dir = "/usr/share/zeroclawlabs/web/dist"' \
'' \
'[risk_profiles.default]' \
'level = "supervised"' \
'auto_approve = ["file_read", "file_write", "file_edit", "memory_recall", "memory_store", "web_search_tool", "web_fetch", "calculator", "glob_search", "content_search", "image_info", "weather", "git_operations"]' \
> /zeroclaw-data/.zeroclaw/config.toml && \
chown -R 65534:65534 /zeroclaw-data
# ββ Stage 2: Runtime (Debian with shell) βββββββββββββββββββββ
FROM debian:bookworm-slim AS runtime
# Install essential tools for agent shell operations
RUN apt-get update && apt-get install -y --no-install-recommends \
bash \
ca-certificates \
curl \
git \
vim-tiny \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/zeroclaw /usr/local/bin/zeroclaw
COPY --from=builder /app/zerocode /usr/local/bin/zerocode
COPY --from=builder /zeroclaw-data /zeroclaw-data
# Install the dashboard at /usr/share/zeroclawlabs/web/dist (outside the
# documented /zeroclaw-data mount) so user volumes do not shadow it (#6400).
COPY --from=web-builder /app/web/dist /usr/share/zeroclawlabs/web/dist
# Environment setup
# Ensure UTF-8 locale so CJK / multibyte input is handled correctly
ENV LANG=C.UTF-8
ENV ZEROCLAW_DATA_DIR=/zeroclaw-data/data
ENV HOME=/zeroclaw-data
# Default provider and model are set in config.toml, not here,
# so config file edits are not silently overridden
ENV ZEROCLAW_GATEWAY_PORT=42617
# API_KEY must be provided at runtime!
WORKDIR /zeroclaw-data
USER 65534:65534
EXPOSE 42617
HEALTHCHECK --interval=60s --timeout=10s --retries=3 --start-period=10s \
CMD ["zeroclaw", "status", "--format=exit-code"]
ENTRYPOINT ["zeroclaw"]
CMD ["daemon"]