Skip to content

Updating from inside the stack

./setup.sh detects when it runs inside one of the dev containers (DooD socket mounted) and rebuilds through a throwaway builder mounted at the HOST paths, where compose's ${HOME} interpolation and relative mounts resolve correctly — and recreating your own container can't kill the script mid-run:

./setup.sh [--tunnel] [--dry-run]

Same flags as on the host; host provisioning (disk, docker, nvidia) is skipped inside since it only matters at first provision. Re-running stays idempotent: only the image is rebuilt and containers recreated — named volumes and the bind-mounted workspaces are never deleted. Host paths are auto-detected from your own container's mount table (HOST_HOME / HOST_REPO env vars override this when detection fails).

Manual equivalent

What setup.sh automates — two traps: compose interpolates ${HOME} and resolves relative mounts using the client's paths (inside a container that is /home/dev and /home/dev/workspaces/...), which the host daemon cannot find; and recreating the container the command is running in kills the command itself.

1. From a running service, update the others. Override the client paths so bind mounts resolve to real host paths:

HOME=<host home> docker compose \
  --project-directory <host path to this repo> \
  --env-file /home/dev/workspaces/ainvironment/.env \
  -f /home/dev/workspaces/ainvironment/docker-compose.yml up -d

2. Full update, including the container you are in. Launch a throwaway builder over the socket, mounted at its own host path so client and daemon agree on every path — nothing in it belongs to the stack, so it can recreate everything:

docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v <host path to this repo>:<host path to this repo> \
  -w <host path to this repo> -e HOME=<host home> \
  ainvironment/dev:latest docker compose up -d

macOS: HOME=/Users/<you>, repo /Users/<you>/workspaces/ainvironment. Linux: HOME=/home/<you>, repo /home/<you>/workspaces/ainvironment.

Rebuilds pick up both changes automatically: a newer OPENCODE_VERSION (or unset for the channel's latest) because nothing masks /home/dev/.opencode, and any extensions added to the Dockerfile's list via the post_start hook.

Add --profile <name> to those calls for anything beyond the defaults — and keep build separate from up. They share one image+tag, so three parallel builders race on latest and fail with AlreadyExists; that split is why setup.sh no longer uses up --build.

Next: Kubernetes — the Helm deployment plan.