Test worked
This commit is contained in:
@@ -8,7 +8,17 @@ Docker scaffold for running Claude Code in an isolated container (see README.md)
|
||||
(image/container name — the default `claudaris` is meant to be overridden
|
||||
per person, e.g. `chris-claude`, so multiple users can each run their own
|
||||
container off this same repo), `DATA_DIR`, and `WORKSPACE_DIR`. `claudaris`
|
||||
sources it if present.
|
||||
sources it if present; `docker-compose.yml` reads the same vars, and
|
||||
`docker compose` picks up `.env` on its own since it lives in the project
|
||||
directory compose runs from — so `claudaris` and plain `docker compose`
|
||||
commands agree without any extra wiring.
|
||||
- `docker-compose.yml` — the actual container definition (build context,
|
||||
image/container/hostname name, volumes); `claudaris` shells out to
|
||||
`docker compose` rather than raw `docker build`/`run`/`exec`. The one
|
||||
mount it can't express is the opt-in SSH mount (see `claudaris start`
|
||||
below), which needs a host path to exist first — that's added via a
|
||||
gitignored `docker-compose.override.yml` that `claudaris start` writes or
|
||||
removes as needed; compose merges it automatically when present.
|
||||
- `Dockerfile` — archlinux base image with bash, git, nodejs/npm, tmux, vim,
|
||||
fastfetch, etc. `files/bash_aliases` is baked in at `/opt/dotfiles/bash_aliases`
|
||||
and `files/bashrc` becomes the image's default `/root/.bashrc` — both are
|
||||
@@ -57,33 +67,39 @@ Docker scaffold for running Claude Code in an isolated container (see README.md)
|
||||
- `config` (alias `configure`) — interactive wizard prompting for `NAME`,
|
||||
`DATA_DIR`, `WORKSPACE_DIR` (showing current/default values, enter to
|
||||
keep) and writing them to `.env`. Re-run any time to update it.
|
||||
- `build` — builds the image, tagged `$NAME` (see `.env` above).
|
||||
- `start` — runs the container as `$NAME` with `--hostname "$NAME"` (so the
|
||||
shell prompt reads `root@$NAME`, e.g. `root@claudaris`, instead of a
|
||||
random container ID). `/root/.bashrc`, `/opt/dotfiles/bash_aliases`, and
|
||||
the two auth files (`~/.claude/.credentials.json`, `~/.claude.json`) are
|
||||
each bind-mounted individually — seeded once (empty, for the auth files;
|
||||
from `files/bashrc`/`files/bash_aliases`, for the dotfiles) into
|
||||
`$DATA_DIR/home/{.bashrc,bash_aliases}` and
|
||||
`$DATA_DIR/claude/{credentials,claude}.json` on the host, so they can be
|
||||
edited/persist without a rebuild — including a coworker dropping in their
|
||||
own aliases. Individual-file mounts matter for the auth files
|
||||
specifically: Claude Code likely saves them atomically (write a temp
|
||||
file, then `rename()` over the target), and `rename()` onto a symlink
|
||||
replaces the symlink instead of writing through it — silently breaking
|
||||
persistence after the first write. A bind mount doesn't have that
|
||||
failure mode, which is why these aren't just symlinked from a directory
|
||||
volume the way an earlier version of this setup did it. `$WORKSPACE_DIR`
|
||||
is mounted at `/projects`. Also offers an opt-in `/root/.ssh` mount
|
||||
(read-only) for reaching other nodes: create `$DATA_DIR/ssh` on the host
|
||||
and populate it before starting the container to enable it. `DATA_DIR`
|
||||
defaults to `/data/$NAME`; `WORKSPACE_DIR` defaults to
|
||||
`/home/$USER/projects` (override via `claudaris config`).
|
||||
- `connect` — `docker start`s `$NAME` (a no-op if it's already running)
|
||||
then attaches to its tmux session, so it also works right after the
|
||||
- `build` — `docker compose build --no-cache --pull` (see `.env` above for
|
||||
`$NAME`).
|
||||
- `start` — `docker compose up -d`, so the shell prompt reads
|
||||
`root@$NAME`, e.g. `root@claudaris`, instead of a random container ID
|
||||
(`hostname:` in `docker-compose.yml`). `/root/.bashrc`,
|
||||
`/opt/dotfiles/bash_aliases`, and the auth files
|
||||
(`~/.claude/.credentials.json`, `~/.claude.json`,
|
||||
`~/.local/share/opencode/auth.json`) are each bind-mounted individually
|
||||
in `docker-compose.yml` — seeded once by `start` (empty, for the auth
|
||||
files; from `files/bashrc`/`files/bash_aliases`, for the dotfiles) into
|
||||
`$DATA_DIR/home/{.bashrc,bash_aliases}`,
|
||||
`$DATA_DIR/claude/{credentials,claude}.json`, and
|
||||
`$DATA_DIR/opencode/auth.json` on the host, so they can be edited/persist
|
||||
without a rebuild — including a coworker dropping in their own aliases.
|
||||
Individual-file mounts matter for the auth files specifically: Claude
|
||||
Code and OpenCode likely save them atomically (write a temp file, then
|
||||
`rename()` over the target), and `rename()` onto a symlink replaces the
|
||||
symlink instead of writing through it — silently breaking persistence
|
||||
after the first write. A bind mount doesn't have that failure mode,
|
||||
which is why these aren't just symlinked from a directory volume the way
|
||||
an earlier version of this setup did it. `$WORKSPACE_DIR` is mounted at
|
||||
`/projects`. Also offers an opt-in `/root/.ssh` mount (read-only) for
|
||||
reaching other nodes: create `$DATA_DIR/ssh` on the host and populate it
|
||||
before starting the container to enable it — `start` writes or removes a
|
||||
gitignored `docker-compose.override.yml` for this mount, since compose
|
||||
can't make a volume conditional on a host path existing the way the
|
||||
script itself can. `DATA_DIR` defaults to `/data/$NAME`; `WORKSPACE_DIR`
|
||||
defaults to `/home/$USER/projects` (override via `claudaris config`).
|
||||
- `connect` — `docker compose up -d` (a no-op if already running) then
|
||||
`docker compose exec claudaris bash`, so it also works right after the
|
||||
container has auto-exited (see `Dockerfile`/entrypoint above).
|
||||
- `remove` (aliases `stop`, `rm`) — stops and removes the container so
|
||||
a subsequent `start` recreates it fresh.
|
||||
- `remove` (aliases `stop`, `rm`) — `docker compose down`, so a subsequent
|
||||
`start` recreates the container fresh.
|
||||
- `help` — usage.
|
||||
- `files/` — plain (non-dot) source files `COPY`'d into the image at build
|
||||
time: `bashrc`/`bash_aliases` (dotfiles — see `Dockerfile` above),
|
||||
@@ -102,22 +118,19 @@ Docker scaffold for running Claude Code in an isolated container (see README.md)
|
||||
## Common commands
|
||||
```bash
|
||||
# build the image
|
||||
docker build -t "$NAME" .
|
||||
docker compose build --no-cache --pull
|
||||
|
||||
# start the container
|
||||
docker run -d \
|
||||
--name "$NAME" \
|
||||
--hostname "$NAME" \
|
||||
-v "$DATA_DIR/home/.bashrc:/root/.bashrc" \
|
||||
-v "$DATA_DIR/home/bash_aliases:/opt/dotfiles/bash_aliases" \
|
||||
-v "$DATA_DIR/claude/credentials.json:/root/.claude/.credentials.json" \
|
||||
-v "$DATA_DIR/claude/claude.json:/root/.claude.json" \
|
||||
-v "$WORKSPACE_DIR:/projects" \
|
||||
"$NAME"
|
||||
docker compose up -d
|
||||
|
||||
# attach to the running container's tmux session
|
||||
docker exec -it "$NAME" tmux
|
||||
# attach to the running container
|
||||
docker compose exec claudaris bash
|
||||
```
|
||||
`docker compose` reads `NAME`/`DATA_DIR`/`WORKSPACE_DIR` from `.env`
|
||||
automatically (no `claudaris` involvement needed), but the host-side seeding
|
||||
`claudaris start` does (dotfiles, auth files, the SSH override) isn't
|
||||
replicated by compose itself — run `claudaris start` at least once per host
|
||||
before using raw compose commands.
|
||||
|
||||
## Notes
|
||||
No test suite or CI — this is infra/config, not application code. Verify changes
|
||||
|
||||
Reference in New Issue
Block a user