-
Notifications
You must be signed in to change notification settings - Fork 3
docs: add custom image guide #215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,199 @@ | ||||||||||
| # Custom Images | ||||||||||
|
|
||||||||||
| This is the guide for people who want their own deva image instead of | ||||||||||
| the stock one. | ||||||||||
|
|
||||||||||
| Common reasons: | ||||||||||
|
|
||||||||||
| - you want extra tools baked in | ||||||||||
| - you want a personal image in your own registry | ||||||||||
| - you want local experiments without waiting for upstream releases | ||||||||||
|
|
||||||||||
| That is fine. deva does not care where the image came from. It cares | ||||||||||
| that the image exists and that the tag you asked for is real. | ||||||||||
|
|
||||||||||
| ## The Two Knobs | ||||||||||
|
|
||||||||||
| Deva picks the runtime image from two host-side variables: | ||||||||||
|
|
||||||||||
| - `DEVA_DOCKER_IMAGE` | ||||||||||
| - `DEVA_DOCKER_TAG` | ||||||||||
|
|
||||||||||
| If you do nothing, it uses: | ||||||||||
|
|
||||||||||
| ```text | ||||||||||
| DEVA_DOCKER_IMAGE=ghcr.io/thevibeworks/deva | ||||||||||
| DEVA_DOCKER_TAG=latest | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| For the rust profile, the default tag becomes `rust`. | ||||||||||
|
|
||||||||||
| Important detail: | ||||||||||
|
|
||||||||||
| - if you set only `DEVA_DOCKER_IMAGE`, `PROFILE=rust` can still change the | ||||||||||
| tag to `rust` | ||||||||||
| - if you want zero surprises, set both `DEVA_DOCKER_IMAGE` and | ||||||||||
| `DEVA_DOCKER_TAG` | ||||||||||
|
|
||||||||||
| ## Build A Local Image | ||||||||||
|
|
||||||||||
| Base image: | ||||||||||
|
|
||||||||||
| ```bash | ||||||||||
| docker build -t deva-local:latest . | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| Rust profile image: | ||||||||||
|
|
||||||||||
| ```bash | ||||||||||
| docker build -f Dockerfile.rust -t deva-local:rust . | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| Then run deva against it: | ||||||||||
|
|
||||||||||
| ```bash | ||||||||||
| DEVA_DOCKER_IMAGE=deva-local \ | ||||||||||
| DEVA_DOCKER_TAG=latest \ | ||||||||||
| deva.sh codex | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| Or for the rust image: | ||||||||||
|
|
||||||||||
| ```bash | ||||||||||
| DEVA_DOCKER_IMAGE=deva-local \ | ||||||||||
| DEVA_DOCKER_TAG=rust \ | ||||||||||
| deva.sh claude | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| Deva checks local images first. If the image is already there, it does | ||||||||||
| not need to pull anything. | ||||||||||
|
|
||||||||||
| ## Build A Personal Registry Image | ||||||||||
|
|
||||||||||
| If you want your own registry namespace, tag it that way from the start: | ||||||||||
|
|
||||||||||
| ```bash | ||||||||||
| docker build -t ghcr.io/yourname/deva:daily . | ||||||||||
| docker push ghcr.io/yourname/deva:daily | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| Then point deva at it: | ||||||||||
|
|
||||||||||
| ```bash | ||||||||||
| export DEVA_DOCKER_IMAGE=ghcr.io/yourname/deva | ||||||||||
| export DEVA_DOCKER_TAG=daily | ||||||||||
| deva.sh codex | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| That is the whole trick. This is not Kubernetes. It is just an image | ||||||||||
| name plus a tag. | ||||||||||
|
|
||||||||||
| ## Keep It Personal | ||||||||||
|
|
||||||||||
| If this is only for you, put the override in `.deva.local`: | ||||||||||
|
|
||||||||||
| ```text | ||||||||||
| DEVA_DOCKER_IMAGE=ghcr.io/yourname/deva | ||||||||||
| DEVA_DOCKER_TAG=daily | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| That file is the right place for personal registry tags, private images, | ||||||||||
| and "I am trying weird stuff" experiments. | ||||||||||
|
|
||||||||||
| If the whole team should use the same custom image, put it in `.deva` | ||||||||||
| instead: | ||||||||||
|
|
||||||||||
| ```text | ||||||||||
| DEVA_DOCKER_IMAGE=ghcr.io/acme/deva | ||||||||||
| DEVA_DOCKER_TAG=team-rust-20260312 | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| Yes, deva's config loader will export those variables for the wrapper. | ||||||||||
| That is intentional. | ||||||||||
|
|
||||||||||
| ## Extend The Official Image Instead Of Starting From Nothing | ||||||||||
|
|
||||||||||
| If you just need a few extra tools, do not rebuild the universe. | ||||||||||
|
|
||||||||||
| Use the published image as your base: | ||||||||||
|
|
||||||||||
| ```dockerfile | ||||||||||
| FROM ghcr.io/thevibeworks/deva:latest | ||||||||||
|
|
||||||||||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||||||||||
| graphviz \ | ||||||||||
| postgresql-client \ | ||||||||||
| && rm -rf /var/lib/apt/lists/* | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| Build and run it: | ||||||||||
|
|
||||||||||
| ```bash | ||||||||||
| docker build -t deva-local:extras . | ||||||||||
| DEVA_DOCKER_IMAGE=deva-local DEVA_DOCKER_TAG=extras deva.sh gemini | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| That is usually the sane move. | ||||||||||
|
|
||||||||||
| ## What Still Comes From The Wrapper | ||||||||||
|
|
||||||||||
| Changing the image does not change the wrapper model. | ||||||||||
|
|
||||||||||
| Deva still controls: | ||||||||||
|
|
||||||||||
| - workspace mounts | ||||||||||
| - auth mounts | ||||||||||
| - config-home wiring | ||||||||||
| - container naming | ||||||||||
| - persistent vs ephemeral behavior | ||||||||||
| - debug and dry-run output | ||||||||||
|
|
||||||||||
| So a custom image is not a custom launcher. It is just a different root | ||||||||||
| filesystem under the same wrapper behavior. | ||||||||||
|
|
||||||||||
| ## Personal Use Without Installing Anything Globally | ||||||||||
|
|
||||||||||
| You do not need to replace your whole system install. | ||||||||||
|
|
||||||||||
| Per-shell: | ||||||||||
|
|
||||||||||
| ```bash | ||||||||||
| DEVA_DOCKER_IMAGE=deva-local \ | ||||||||||
| DEVA_DOCKER_TAG=latest \ | ||||||||||
| deva.sh codex | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| Per-project: | ||||||||||
|
|
||||||||||
| ```text | ||||||||||
| # .deva.local | ||||||||||
| DEVA_DOCKER_IMAGE=deva-local | ||||||||||
| DEVA_DOCKER_TAG=latest | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| That way your personal image only affects the project where you meant to | ||||||||||
| use it. Amazing concept. | ||||||||||
|
|
||||||||||
| ## Gotchas | ||||||||||
|
|
||||||||||
| - If you set only the image and forget the tag, profile defaults may | ||||||||||
| still pick `latest` or `rust`. | ||||||||||
| - If the image is private, pulls need auth. Public docs pointing at a | ||||||||||
| private image are broken by definition. | ||||||||||
| - If you build a custom image that removes expected tools or paths, | ||||||||||
| deva will not magically repair your bad Dockerfile. | ||||||||||
| - If your image tag does not exist locally and cannot be pulled, deva | ||||||||||
| fails fast. Good. Silent nonsense would be worse. | ||||||||||
|
||||||||||
| fails fast. Good. Silent nonsense would be worse. | |
| will warn and fall back to a local `rust` or `latest` tag when one | |
| exists; if no suitable fallback exists, it errors instead. Silent | |
| nonsense would be worse. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove incorrect fail-fast guarantee for missing image tags
This bullet says deva will "fail fast" when the requested tag is missing and cannot be pulled, but check_image() in deva.sh first falls back to any local rust/latest tag (for tag in rust latest and DEVA_DOCKER_TAG="$fallback_tag"). In environments where one fallback tag exists locally, deva proceeds with a different image instead of failing, so this guidance is inaccurate and can mislead users during reproducibility/debugging.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This statement implies deva strictly requires the requested tag to exist, but
deva.shcan automatically fall back to another locally-available tag (currently prefersrustthenlatest) if the requested tag is missing and the pull fails. Please adjust this wording to reflect the fallback + warning behavior, or explicitly note that the requested tag may be substituted when a compatible local image exists.