返回 CodeWhale
DOCKER.md
根目录 / docs / DOCKER.md
1 # Docker
2
3 Codewhale publishes a multi-arch Linux image to GitHub Container Registry
4 for each release.
5
6 ```bash
7 docker pull ghcr.io/hmbown/codewhale:latest
8 ```
9
10 ## Quick start
11
12 Run the published image with a Docker-managed data volume:
13
14 ```bash
15 docker volume create codewhale-home
16
17 docker run --rm -it \
18 -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
19 -v codewhale-home:/home/codewhale/.codewhale \
20 -v "$PWD:/workspace" \
21 -w /workspace \
22 ghcr.io/hmbown/codewhale:latest
23 ```
24
25 Use a pinned release tag for reproducible installs:
26
27 ```bash
28 docker run --rm -it \
29 -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
30 -v codewhale-home:/home/codewhale/.codewhale \
31 -v "$PWD:/workspace" \
32 -w /workspace \
33 ghcr.io/hmbown/codewhale:vX.Y.Z
34 ```
35
36 Replace `vX.Y.Z` with a tag from
37 [GitHub Releases](https://github.com/Hmbown/CodeWhale/releases).
38
39 ## Default image contract
40
41 `ghcr.io/hmbown/codewhale:latest` and the semver tags are conservative runtime
42 images:
43
44 - the container runs as the non-root `codewhale` user with UID/GID `1000:1000`
45 - the image does not grant passwordless `sudo`
46 - the image is meant to run Codewhale against mounted workspaces, not to mutate
47 the base operating system at runtime
48 - user state belongs in a volume mounted at `/home/codewhale/.codewhale`
49
50 That default is intentional. Keep using it for the smallest trust boundary. If a
51 project needs `apt-get`, compiler toolchains, Node/Python package managers,
52 custom CA certificates, or other host-like setup inside Docker, build an
53 explicit toolbox image instead of changing the default image contract.
54
55 ## Opt-in toolbox/custom image
56
57 The repository includes an example
58 [`docs/examples/Dockerfile.toolbox`](examples/Dockerfile.toolbox) that extends
59 the official image with passwordless `sudo` and common development packages.
60 Build it with a pinned Codewhale tag when you want repeatable project
61 environments:
62
63 ```bash
64 docker build -f docs/examples/Dockerfile.toolbox \
65 --build-arg CODEWHALE_IMAGE=ghcr.io/hmbown/codewhale:vX.Y.Z \
66 --build-arg TOOLBOX_PACKAGES="git openssh-client curl build-essential pkg-config python3 python3-pip nodejs npm" \
67 -t codewhale-toolbox:my-project .
68 ```
69
70 Use `latest` only for throwaway testing. For shared projects, keep the
71 `CODEWHALE_IMAGE` value pinned and review package additions like any other
72 development-environment change.
73
74 Run the toolbox image with the same workspace and state mounts:
75
76 ```bash
77 docker volume create codewhale-my-project-home
78
79 docker run --rm -it \
80 -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
81 -v codewhale-my-project-home:/home/codewhale/.codewhale \
82 -v "$PWD:/workspace" \
83 -w /workspace \
84 codewhale-toolbox:my-project
85 ```
86
87 Inside this opt-in image, Codewhale can use commands such as
88 `sudo apt-get update` and `sudo apt-get install -y <package>`. For repeatable
89 containers, prefer baking those packages into the toolbox Dockerfile instead of
90 letting a long-lived container drift.
91
92 Do not bake API keys, SSH private keys, or other secrets into custom images.
93 Pass API keys at runtime and mount any SSH material deliberately, preferably
94 read-only and only for projects that need it.
95
96 ### Compose toolbox template
97
98 If you prefer a repeatable `docker compose` entry point, use
99 [`docs/examples/compose.toolbox.yml`](examples/compose.toolbox.yml). It builds
100 the toolbox image from [`docs/examples/Dockerfile.toolbox`](examples/Dockerfile.toolbox)
101 and keeps the project state volume explicit:
102
103 ```bash
104 CODEWHALE_IMAGE=ghcr.io/hmbown/codewhale:vX.Y.Z \
105 CODEWHALE_TOOLBOX_IMAGE=codewhale-toolbox:my-project \
106 CODEWHALE_HOME_VOLUME=codewhale-my-project-home \
107 CODEWHALE_WORKSPACE="$PWD" \
108 docker compose -f docs/examples/compose.toolbox.yml run --rm codewhale
109 ```
110
111 Use a different `CODEWHALE_TOOLBOX_IMAGE` and `CODEWHALE_HOME_VOLUME` for each
112 project that needs an independent toolchain or independent `.codewhale` state.
113 The Compose file also shows opt-in, read-only mounts for SSH material and local
114 CA certificates; keep those commented out unless the project needs them.
115
116 ## Multiple independent projects
117
118 Use one named state volume per project so sessions, config, skills, memory, and
119 the offline queue do not bleed across workspaces:
120
121 ```bash
122 project="$(basename "$PWD")"
123 image="codewhale-toolbox:${project}"
124 docker volume create "codewhale-${project}-home"
125
126 docker run --rm -it \
127 --name "codewhale-${project}" \
128 -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
129 -v "codewhale-${project}-home:/home/codewhale/.codewhale" \
130 -v "$PWD:/workspace" \
131 -w /workspace \
132 "$image"
133 ```
134
135 For projects with different toolchains, build different toolbox tags, for
136 example `codewhale-toolbox:frontend` and `codewhale-toolbox:backend`. The
137 separate launcher idea discussed in issue #2217 can build on this contract, but
138 it is intentionally outside the core Docker image.
139
140 ## Project bootstrap scripts
141
142 Codewhale does not automatically execute `.codewhale/setup.sh` or legacy
143 `.deepseek/setup.sh`. If you keep one of those files as a local project recipe,
144 run it explicitly. For shared team setup, prefer a committed project script or
145 the toolbox Dockerfile so the environment can be reviewed and rebuilt.
146
147 For example, to run a committed bootstrap script before starting Codewhale:
148
149 ```bash
150 docker run --rm -it \
151 -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
152 -v codewhale-my-project-home:/home/codewhale/.codewhale \
153 -v "$PWD:/workspace" \
154 -w /workspace \
155 --entrypoint bash \
156 codewhale-toolbox:my-project \
157 -lc './scripts/bootstrap-dev.sh && exec codewhale'
158 ```
159
160 Use the toolbox image for bootstrap scripts that need `sudo`. The default image
161 will not elevate privileges.
162
163 ## Custom CA certificates and proxies
164
165 For corporate proxies, dev-sidecar, or self-signed internal services, prefer
166 baking trusted CA certificates into a custom toolbox image:
167
168 ```dockerfile
169 USER root
170 COPY docker/certs/*.crt /usr/local/share/ca-certificates/
171 RUN update-ca-certificates
172 USER codewhale
173 ```
174
175 All files copied into `/usr/local/share/ca-certificates/` must use the `.crt`
176 extension. Keep private CA material out of public images.
177
178 For a local-only run, mount certificates read-only and update the trust store at
179 container start:
180
181 ```bash
182 docker run --rm -it \
183 -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
184 -v codewhale-my-project-home:/home/codewhale/.codewhale \
185 -v "$PWD:/workspace" \
186 -v "$PWD/docker/certs:/usr/local/share/ca-certificates/local:ro" \
187 -w /workspace \
188 --entrypoint bash \
189 codewhale-toolbox:my-project \
190 -lc 'sudo update-ca-certificates && exec codewhale'
191 ```
192
193 This CA workflow requires the opt-in toolbox image because the default image
194 does not include passwordless `sudo`.
195
196 ## Local build
197
198 Build the image locally from a checkout:
199
200 ```bash
201 docker build -t codewhale .
202 ```
203
204 Then run it with the same Docker-managed data volume:
205
206 ```bash
207 docker run --rm -it \
208 -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
209 -v codewhale-home:/home/codewhale/.codewhale \
210 -v "$PWD:/workspace" \
211 -w /workspace \
212 codewhale
213 ```
214
215 Docker Hub publishing is not configured; GHCR is the supported prebuilt image
216 registry.
217
218 ## Environment variables
219
220 | Variable | Required | Description |
221 |-----------------------|----------|--------------------------------------------------|
222 | `DEEPSEEK_API_KEY` | yes | DeepSeek API key |
223 | `DEEPSEEK_BASE_URL` | no | Custom API base URL (e.g. `https://api.deepseek.com`) |
224 | `DEEPSEEK_NO_COLOR` | no | Set to `1` to disable terminal colour output |
225
226 ## Volumes
227
228 Mount `/home/codewhale/.codewhale` to persist sessions, config, skills, memory,
229 and the offline queue across container restarts. The image also keeps
230 `/home/codewhale/.deepseek` available for legacy compatibility. A
231 Docker-managed named volume is the safest default because Docker creates it with
232 ownership the container can write:
233
234 ```bash
235 -v codewhale-home:/home/codewhale/.codewhale
236 ```
237
238 Without this mount the container starts fresh each time.
239
240 If you bind-mount an existing host directory instead, the image runs as the
241 non-root `codewhale` user with UID/GID `1000:1000`. The mounted directory must be
242 writable by that user, or startup can fail while creating runtime directories
243 under `.codewhale/tasks`. On Linux hosts, either use the named volume above or
244 prepare the bind mount explicitly:
245
246 ```bash
247 mkdir -p ~/.codewhale
248 sudo chown -R 1000:1000 ~/.codewhale
249
250 docker run --rm -it \
251 -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
252 -v ~/.codewhale:/home/codewhale/.codewhale \
253 ghcr.io/hmbown/codewhale:latest
254 ```
255
256 That `chown` changes ownership of the host `~/.codewhale` directory. Skip it if
257 you do not want the container UID to own your local config, and use a named
258 volume instead.
259
260 ## Non-interactive / pipeline usage
261
262 When stdin is not a TTY, `codewhale` drops to the dispatcher's one-shot mode
263 (`codewhale -c "…"`). Pipe a prompt on stdin:
264
265 ```bash
266 echo "Explain the Cargo.toml in structured English." | \
267 docker run --rm -i -e DEEPSEEK_API_KEY ghcr.io/hmbown/codewhale:latest
268 ```
269
270 ## Building locally
271
272 ```bash
273 # Single platform (your host architecture)
274 docker build -t codewhale .
275
276 # Multi-platform (requires a builder with emulation)
277 docker buildx create --use
278 docker buildx build --platform linux/amd64,linux/arm64 -t codewhale .
279 ```
280
281 ## Devcontainer
282
283 The repository includes a [`.devcontainer/devcontainer.json`](../.devcontainer/devcontainer.json)
284 configuration for VS Code / GitHub Codespaces. It builds a dedicated development
285 image with the Rust toolchain, Git, `pkg-config`, and the DBus development headers
286 required by the workspace. The first open runs `cargo build --locked` and installs
287 rust-analyzer and the other editor extensions.
288
289 The source checkout remains mounted from the host. CodeWhale state and Cargo build
290 artifacts use Docker named volumes instead, so the configuration works when VS Code
291 cannot provide a POSIX-style `HOME` variable (notably on Windows), and builds do not
292 write thousands of small files through a Windows bind mount. Rebuild the container
293 after changing the Dev Container configuration.
294
295 ## Release status
296
297 Docker image publishing is part of the release gate. The image is published to
298 GHCR for `linux/amd64` and `linux/arm64` with semver tags plus `latest`.
299
299 lines MARKDOWN