diff --git a/.gitignore b/.gitignore index 18f3f2952..147a3a32f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules .env +docker-compose.extra.yml dist *.bun-build pnpm-lock.yaml diff --git a/docker-setup.sh b/docker-setup.sh index 3e168e4d2..9b8bdfff9 100755 --- a/docker-setup.sh +++ b/docker-setup.sh @@ -3,7 +3,10 @@ set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" COMPOSE_FILE="$ROOT_DIR/docker-compose.yml" +EXTRA_COMPOSE_FILE="$ROOT_DIR/docker-compose.extra.yml" IMAGE_NAME="${CLAWDBOT_IMAGE:-clawdbot:local}" +EXTRA_MOUNTS="${CLAWDBOT_EXTRA_MOUNTS:-}" +HOME_VOLUME_NAME="${CLAWDBOT_HOME_VOLUME:-}" require_cmd() { if ! command -v "$1" >/dev/null 2>&1; then @@ -41,6 +44,75 @@ PY fi export CLAWDBOT_GATEWAY_TOKEN +COMPOSE_FILES=("$COMPOSE_FILE") +COMPOSE_ARGS=() + +write_extra_compose() { + local mounts_csv="$1" + local home_volume="$2" + local -a mounts=() + local mount + + # Split on commas; ignore empty entries. + IFS=',' read -r -a mounts <<<"$mounts_csv" + + cat >"$EXTRA_COMPOSE_FILE" <<'YAML' +services: + clawdbot-gateway: + volumes: +YAML + + if [[ -n "$home_volume" ]]; then + printf ' - %s:/home/node\n' "$home_volume" >>"$EXTRA_COMPOSE_FILE" + fi + + for mount in "${mounts[@]}"; do + mount="${mount#"${mount%%[![:space:]]*}"}" + mount="${mount%"${mount##*[![:space:]]}"}" + if [[ -z "$mount" ]]; then + continue + fi + printf ' - %s\n' "$mount" >>"$EXTRA_COMPOSE_FILE" + done + + cat >>"$EXTRA_COMPOSE_FILE" <<'YAML' + clawdbot-cli: + volumes: +YAML + + if [[ -n "$home_volume" ]]; then + printf ' - %s:/home/node\n' "$home_volume" >>"$EXTRA_COMPOSE_FILE" + fi + + for mount in "${mounts[@]}"; do + mount="${mount#"${mount%%[![:space:]]*}"}" + mount="${mount%"${mount##*[![:space:]]}"}" + if [[ -z "$mount" ]]; then + continue + fi + printf ' - %s\n' "$mount" >>"$EXTRA_COMPOSE_FILE" + done + + if [[ -n "$home_volume" ]]; then + cat >>"$EXTRA_COMPOSE_FILE" < Building Docker image: $IMAGE_NAME" docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/Dockerfile" "$ROOT_DIR" @@ -98,21 +172,21 @@ echo " - Gateway token: $CLAWDBOT_GATEWAY_TOKEN" echo " - Tailscale exposure: Off" echo " - Install Gateway daemon: No" echo "" -docker compose -f "$COMPOSE_FILE" run --rm clawdbot-cli onboard --no-install-daemon +docker compose "${COMPOSE_ARGS[@]}" run --rm clawdbot-cli onboard --no-install-daemon echo "" echo "==> Provider setup (optional)" echo "WhatsApp (QR):" -echo " docker compose -f $COMPOSE_FILE run --rm clawdbot-cli providers login" +echo " ${COMPOSE_HINT} run --rm clawdbot-cli providers login" echo "Telegram (bot token):" -echo " docker compose -f $COMPOSE_FILE run --rm clawdbot-cli providers add --provider telegram --token " +echo " ${COMPOSE_HINT} run --rm clawdbot-cli providers add --provider telegram --token " echo "Discord (bot token):" -echo " docker compose -f $COMPOSE_FILE run --rm clawdbot-cli providers add --provider discord --token " +echo " ${COMPOSE_HINT} run --rm clawdbot-cli providers add --provider discord --token " echo "Docs: https://docs.clawd.bot/providers" echo "" echo "==> Starting gateway" -docker compose -f "$COMPOSE_FILE" up -d clawdbot-gateway +docker compose "${COMPOSE_ARGS[@]}" up -d clawdbot-gateway echo "" echo "Gateway running with host port mapping." @@ -122,5 +196,5 @@ echo "Workspace: $CLAWDBOT_WORKSPACE_DIR" echo "Token: $CLAWDBOT_GATEWAY_TOKEN" echo "" echo "Commands:" -echo " docker compose -f $COMPOSE_FILE logs -f clawdbot-gateway" -echo " docker compose -f $COMPOSE_FILE exec clawdbot-gateway node dist/index.js health --token \"$CLAWDBOT_GATEWAY_TOKEN\"" +echo " ${COMPOSE_HINT} logs -f clawdbot-gateway" +echo " ${COMPOSE_HINT} exec clawdbot-gateway node dist/index.js health --token \"$CLAWDBOT_GATEWAY_TOKEN\"" diff --git a/docs/install/docker.md b/docs/install/docker.md index 68cfe9899..bb2ac6c8e 100644 --- a/docs/install/docker.md +++ b/docs/install/docker.md @@ -61,6 +61,51 @@ docker compose run --rm clawdbot-cli onboard docker compose up -d clawdbot-gateway ``` +### Extra mounts (optional) + +If you want to mount additional host directories into the containers, set +`CLAWDBOT_EXTRA_MOUNTS` before running `docker-setup.sh`. This accepts a +comma-separated list of Docker bind mounts and applies them to both +`clawdbot-gateway` and `clawdbot-cli` by generating `docker-compose.extra.yml`. + +Example: + +```bash +export CLAWDBOT_EXTRA_MOUNTS="$HOME/.codex:/home/node/.codex:ro,$HOME/github:/home/node/github:rw" +./docker-setup.sh +``` + +Notes: +- Paths must be shared with Docker Desktop on macOS/Windows. +- If you edit `CLAWDBOT_EXTRA_MOUNTS`, rerun `docker-setup.sh` to regenerate the + extra compose file. + +### Persist the entire container home (optional) + +If you want `/home/node` to persist across container recreation, set a named +volume via `CLAWDBOT_HOME_VOLUME`. This creates a Docker volume and mounts it at +`/home/node`, while keeping the standard config/workspace bind mounts. + +Example: + +```bash +export CLAWDBOT_HOME_VOLUME="clawdbot_home" +./docker-setup.sh +``` + +You can combine this with extra mounts: + +```bash +export CLAWDBOT_HOME_VOLUME="clawdbot_home" +export CLAWDBOT_EXTRA_MOUNTS="$HOME/.codex:/home/node/.codex:ro,$HOME/github:/home/node/github:rw" +./docker-setup.sh +``` + +Notes: +- If you change `CLAWDBOT_HOME_VOLUME`, rerun `docker-setup.sh` to regenerate the + extra compose file. +- The named volume persists until removed with `docker volume rm `. + ### Faster rebuilds (recommended) To speed up rebuilds, order your Dockerfile so dependency layers are cached.