|
| 1 | +# Custom Images |
| 2 | + |
| 3 | +This is the guide for people who want their own deva image instead of |
| 4 | +the stock one. |
| 5 | + |
| 6 | +Common reasons: |
| 7 | + |
| 8 | +- you want extra tools baked in |
| 9 | +- you want a personal image in your own registry |
| 10 | +- you want local experiments without waiting for upstream releases |
| 11 | + |
| 12 | +That is fine. deva does not care where the image came from. It cares |
| 13 | +that the image exists and that the tag you asked for is real. |
| 14 | + |
| 15 | +## The Two Knobs |
| 16 | + |
| 17 | +Deva picks the runtime image from two host-side variables: |
| 18 | + |
| 19 | +- `DEVA_DOCKER_IMAGE` |
| 20 | +- `DEVA_DOCKER_TAG` |
| 21 | + |
| 22 | +If you do nothing, it uses: |
| 23 | + |
| 24 | +```text |
| 25 | +DEVA_DOCKER_IMAGE=ghcr.io/thevibeworks/deva |
| 26 | +DEVA_DOCKER_TAG=latest |
| 27 | +``` |
| 28 | + |
| 29 | +For the rust profile, the default tag becomes `rust`. |
| 30 | + |
| 31 | +Important detail: |
| 32 | + |
| 33 | +- if you set only `DEVA_DOCKER_IMAGE`, `PROFILE=rust` can still change the |
| 34 | + tag to `rust` |
| 35 | +- if you want zero surprises, set both `DEVA_DOCKER_IMAGE` and |
| 36 | + `DEVA_DOCKER_TAG` |
| 37 | + |
| 38 | +## Build A Local Image |
| 39 | + |
| 40 | +Base image: |
| 41 | + |
| 42 | +```bash |
| 43 | +docker build -t deva-local:latest . |
| 44 | +``` |
| 45 | + |
| 46 | +Rust profile image: |
| 47 | + |
| 48 | +```bash |
| 49 | +docker build -f Dockerfile.rust -t deva-local:rust . |
| 50 | +``` |
| 51 | + |
| 52 | +Then run deva against it: |
| 53 | + |
| 54 | +```bash |
| 55 | +DEVA_DOCKER_IMAGE=deva-local \ |
| 56 | +DEVA_DOCKER_TAG=latest \ |
| 57 | +deva.sh codex |
| 58 | +``` |
| 59 | + |
| 60 | +Or for the rust image: |
| 61 | + |
| 62 | +```bash |
| 63 | +DEVA_DOCKER_IMAGE=deva-local \ |
| 64 | +DEVA_DOCKER_TAG=rust \ |
| 65 | +deva.sh claude |
| 66 | +``` |
| 67 | + |
| 68 | +Deva checks local images first. If the image is already there, it does |
| 69 | +not need to pull anything. |
| 70 | + |
| 71 | +## Build A Personal Registry Image |
| 72 | + |
| 73 | +If you want your own registry namespace, tag it that way from the start: |
| 74 | + |
| 75 | +```bash |
| 76 | +docker build -t ghcr.io/yourname/deva:daily . |
| 77 | +docker push ghcr.io/yourname/deva:daily |
| 78 | +``` |
| 79 | + |
| 80 | +Then point deva at it: |
| 81 | + |
| 82 | +```bash |
| 83 | +export DEVA_DOCKER_IMAGE=ghcr.io/yourname/deva |
| 84 | +export DEVA_DOCKER_TAG=daily |
| 85 | +deva.sh codex |
| 86 | +``` |
| 87 | + |
| 88 | +That is the whole trick. This is not Kubernetes. It is just an image |
| 89 | +name plus a tag. |
| 90 | + |
| 91 | +## Keep It Personal |
| 92 | + |
| 93 | +If this is only for you, put the override in `.deva.local`: |
| 94 | + |
| 95 | +```text |
| 96 | +DEVA_DOCKER_IMAGE=ghcr.io/yourname/deva |
| 97 | +DEVA_DOCKER_TAG=daily |
| 98 | +``` |
| 99 | + |
| 100 | +That file is the right place for personal registry tags, private images, |
| 101 | +and "I am trying weird stuff" experiments. |
| 102 | + |
| 103 | +If the whole team should use the same custom image, put it in `.deva` |
| 104 | +instead: |
| 105 | + |
| 106 | +```text |
| 107 | +DEVA_DOCKER_IMAGE=ghcr.io/acme/deva |
| 108 | +DEVA_DOCKER_TAG=team-rust-20260312 |
| 109 | +``` |
| 110 | + |
| 111 | +Yes, deva's config loader will export those variables for the wrapper. |
| 112 | +That is intentional. |
| 113 | + |
| 114 | +## Extend The Official Image Instead Of Starting From Nothing |
| 115 | + |
| 116 | +If you just need a few extra tools, do not rebuild the universe. |
| 117 | + |
| 118 | +Use the published image as your base: |
| 119 | + |
| 120 | +```dockerfile |
| 121 | +FROM ghcr.io/thevibeworks/deva:latest |
| 122 | + |
| 123 | +RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 124 | + graphviz \ |
| 125 | + postgresql-client \ |
| 126 | + && rm -rf /var/lib/apt/lists/* |
| 127 | +``` |
| 128 | + |
| 129 | +Build and run it: |
| 130 | + |
| 131 | +```bash |
| 132 | +docker build -t deva-local:extras . |
| 133 | +DEVA_DOCKER_IMAGE=deva-local DEVA_DOCKER_TAG=extras deva.sh gemini |
| 134 | +``` |
| 135 | + |
| 136 | +That is usually the sane move. |
| 137 | + |
| 138 | +## What Still Comes From The Wrapper |
| 139 | + |
| 140 | +Changing the image does not change the wrapper model. |
| 141 | + |
| 142 | +Deva still controls: |
| 143 | + |
| 144 | +- workspace mounts |
| 145 | +- auth mounts |
| 146 | +- config-home wiring |
| 147 | +- container naming |
| 148 | +- persistent vs ephemeral behavior |
| 149 | +- debug and dry-run output |
| 150 | + |
| 151 | +So a custom image is not a custom launcher. It is just a different root |
| 152 | +filesystem under the same wrapper behavior. |
| 153 | + |
| 154 | +## Personal Use Without Installing Anything Globally |
| 155 | + |
| 156 | +You do not need to replace your whole system install. |
| 157 | + |
| 158 | +Per-shell: |
| 159 | + |
| 160 | +```bash |
| 161 | +DEVA_DOCKER_IMAGE=deva-local \ |
| 162 | +DEVA_DOCKER_TAG=latest \ |
| 163 | +deva.sh codex |
| 164 | +``` |
| 165 | + |
| 166 | +Per-project: |
| 167 | + |
| 168 | +```text |
| 169 | +# .deva.local |
| 170 | +DEVA_DOCKER_IMAGE=deva-local |
| 171 | +DEVA_DOCKER_TAG=latest |
| 172 | +``` |
| 173 | + |
| 174 | +That way your personal image only affects the project where you meant to |
| 175 | +use it. Amazing concept. |
| 176 | + |
| 177 | +## Gotchas |
| 178 | + |
| 179 | +- If you set only the image and forget the tag, profile defaults may |
| 180 | + still pick `latest` or `rust`. |
| 181 | +- If the image is private, pulls need auth. Public docs pointing at a |
| 182 | + private image are broken by definition. |
| 183 | +- If you build a custom image that removes expected tools or paths, |
| 184 | + deva will not magically repair your bad Dockerfile. |
| 185 | +- If your image tag does not exist locally and cannot be pulled, deva |
| 186 | + fails fast. Good. Silent nonsense would be worse. |
| 187 | + |
| 188 | +## Sanity Check |
| 189 | + |
| 190 | +Use this before blaming the wrapper: |
| 191 | + |
| 192 | +```bash |
| 193 | +DEVA_DOCKER_IMAGE=deva-local \ |
| 194 | +DEVA_DOCKER_TAG=latest \ |
| 195 | +deva.sh codex --debug --dry-run |
| 196 | +``` |
| 197 | + |
| 198 | +If the printed image is wrong, your override is wrong. |
| 199 | +If the printed image is right, the problem is somewhere else. |
0 commit comments