Merge branch 'docs/2217-container-toolbox-contract' into integration/v0.8.47-unified
This commit is contained in:
+138
@@ -36,6 +36,144 @@ docker run --rm -it \
|
||||
Replace `vX.Y.Z` with a tag from
|
||||
[GitHub Releases](https://github.com/Hmbown/CodeWhale/releases).
|
||||
|
||||
## Default image contract
|
||||
|
||||
`ghcr.io/hmbown/codewhale:latest` and the semver tags are conservative runtime
|
||||
images:
|
||||
|
||||
- the container runs as the non-root `codewhale` user with UID/GID `1000:1000`
|
||||
- the image does not grant passwordless `sudo`
|
||||
- the image is meant to run CodeWhale against mounted workspaces, not to mutate
|
||||
the base operating system at runtime
|
||||
- user state belongs in a volume mounted at `/home/codewhale/.deepseek`
|
||||
|
||||
That default is intentional. Keep using it for the smallest trust boundary. If a
|
||||
project needs `apt-get`, compiler toolchains, Node/Python package managers,
|
||||
custom CA certificates, or other host-like setup inside Docker, build an
|
||||
explicit toolbox image instead of changing the default image contract.
|
||||
|
||||
## Opt-in toolbox/custom image
|
||||
|
||||
The repository includes an example
|
||||
[`docs/examples/Dockerfile.toolbox`](examples/Dockerfile.toolbox) that extends
|
||||
the official image with passwordless `sudo` and common development packages.
|
||||
Build it with a pinned CodeWhale tag when you want repeatable project
|
||||
environments:
|
||||
|
||||
```bash
|
||||
docker build -f docs/examples/Dockerfile.toolbox \
|
||||
--build-arg CODEWHALE_IMAGE=ghcr.io/hmbown/codewhale:vX.Y.Z \
|
||||
--build-arg TOOLBOX_PACKAGES="git openssh-client curl build-essential pkg-config python3 python3-pip nodejs npm" \
|
||||
-t codewhale-toolbox:my-project .
|
||||
```
|
||||
|
||||
Use `latest` only for throwaway testing. For shared projects, keep the
|
||||
`CODEWHALE_IMAGE` value pinned and review package additions like any other
|
||||
development-environment change.
|
||||
|
||||
Run the toolbox image with the same workspace and state mounts:
|
||||
|
||||
```bash
|
||||
docker volume create codewhale-my-project-home
|
||||
|
||||
docker run --rm -it \
|
||||
-e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
|
||||
-v codewhale-my-project-home:/home/codewhale/.deepseek \
|
||||
-v "$PWD:/workspace" \
|
||||
-w /workspace \
|
||||
codewhale-toolbox:my-project
|
||||
```
|
||||
|
||||
Inside this opt-in image, CodeWhale can use commands such as
|
||||
`sudo apt-get update` and `sudo apt-get install -y <package>`. For repeatable
|
||||
containers, prefer baking those packages into the toolbox Dockerfile instead of
|
||||
letting a long-lived container drift.
|
||||
|
||||
Do not bake API keys, SSH private keys, or other secrets into custom images.
|
||||
Pass API keys at runtime and mount any SSH material deliberately, preferably
|
||||
read-only and only for projects that need it.
|
||||
|
||||
## Multiple independent projects
|
||||
|
||||
Use one named state volume per project so sessions, config, skills, memory, and
|
||||
the offline queue do not bleed across workspaces:
|
||||
|
||||
```bash
|
||||
project="$(basename "$PWD")"
|
||||
image="codewhale-toolbox:${project}"
|
||||
docker volume create "codewhale-${project}-home"
|
||||
|
||||
docker run --rm -it \
|
||||
--name "codewhale-${project}" \
|
||||
-e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
|
||||
-v "codewhale-${project}-home:/home/codewhale/.deepseek" \
|
||||
-v "$PWD:/workspace" \
|
||||
-w /workspace \
|
||||
"$image"
|
||||
```
|
||||
|
||||
For projects with different toolchains, build different toolbox tags, for
|
||||
example `codewhale-toolbox:frontend` and `codewhale-toolbox:backend`. The
|
||||
separate launcher idea discussed in issue #2217 can build on this contract, but
|
||||
it is intentionally outside the core Docker image.
|
||||
|
||||
## Project bootstrap scripts
|
||||
|
||||
CodeWhale does not automatically execute `.deepseek/setup.sh` or
|
||||
`.codewhale/setup.sh`. If you keep one of those files as a local project
|
||||
recipe, run it explicitly. For shared team setup, prefer a committed project
|
||||
script or the toolbox Dockerfile so the environment can be reviewed and
|
||||
rebuilt.
|
||||
|
||||
For example, to run a committed bootstrap script before starting CodeWhale:
|
||||
|
||||
```bash
|
||||
docker run --rm -it \
|
||||
-e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
|
||||
-v codewhale-my-project-home:/home/codewhale/.deepseek \
|
||||
-v "$PWD:/workspace" \
|
||||
-w /workspace \
|
||||
--entrypoint bash \
|
||||
codewhale-toolbox:my-project \
|
||||
-lc './scripts/bootstrap-dev.sh && exec codewhale'
|
||||
```
|
||||
|
||||
Use the toolbox image for bootstrap scripts that need `sudo`. The default image
|
||||
will not elevate privileges.
|
||||
|
||||
## Custom CA certificates and proxies
|
||||
|
||||
For corporate proxies, dev-sidecar, or self-signed internal services, prefer
|
||||
baking trusted CA certificates into a custom toolbox image:
|
||||
|
||||
```dockerfile
|
||||
USER root
|
||||
COPY docker/certs/*.crt /usr/local/share/ca-certificates/
|
||||
RUN update-ca-certificates
|
||||
USER codewhale
|
||||
```
|
||||
|
||||
All files copied into `/usr/local/share/ca-certificates/` must use the `.crt`
|
||||
extension. Keep private CA material out of public images.
|
||||
|
||||
For a local-only run, mount certificates read-only and update the trust store at
|
||||
container start:
|
||||
|
||||
```bash
|
||||
docker run --rm -it \
|
||||
-e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
|
||||
-v codewhale-my-project-home:/home/codewhale/.deepseek \
|
||||
-v "$PWD:/workspace" \
|
||||
-v "$PWD/docker/certs:/usr/local/share/ca-certificates/local:ro" \
|
||||
-w /workspace \
|
||||
--entrypoint bash \
|
||||
codewhale-toolbox:my-project \
|
||||
-lc 'sudo update-ca-certificates && exec codewhale'
|
||||
```
|
||||
|
||||
This CA workflow requires the opt-in toolbox image because the default image
|
||||
does not include passwordless `sudo`.
|
||||
|
||||
## Local build
|
||||
|
||||
Build the image locally from a checkout:
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
#
|
||||
# Opt-in CodeWhale toolbox image.
|
||||
#
|
||||
# The published ghcr.io/hmbown/codewhale:latest image intentionally stays
|
||||
# minimal, non-root, and without passwordless sudo. Use this Dockerfile only for
|
||||
# workspaces where you deliberately want package installation, custom CA setup,
|
||||
# or project-specific build tools inside the container.
|
||||
#
|
||||
# Example:
|
||||
# docker build -f docs/examples/Dockerfile.toolbox \
|
||||
# --build-arg CODEWHALE_IMAGE=ghcr.io/hmbown/codewhale:vX.Y.Z \
|
||||
# --build-arg TOOLBOX_PACKAGES="git openssh-client curl build-essential pkg-config python3 python3-pip nodejs npm" \
|
||||
# -t codewhale-toolbox:my-project .
|
||||
|
||||
ARG CODEWHALE_IMAGE=ghcr.io/hmbown/codewhale:latest
|
||||
FROM ${CODEWHALE_IMAGE}
|
||||
|
||||
USER root
|
||||
|
||||
ARG TOOLBOX_PACKAGES="git openssh-client curl build-essential pkg-config python3 python3-pip nodejs npm"
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends sudo ${TOOLBOX_PACKAGES} \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& printf '%s\n' 'codewhale ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/codewhale-nopasswd \
|
||||
&& chmod 0440 /etc/sudoers.d/codewhale-nopasswd
|
||||
|
||||
USER codewhale
|
||||
WORKDIR /workspace
|
||||
Reference in New Issue
Block a user