From 5d71753086677cd8392400d546206048bf7880c2 Mon Sep 17 00:00:00 2001 From: johba Date: Sat, 8 Nov 2025 14:08:46 +0100 Subject: [PATCH] migrate/podman-to-docker (#92) podman to docker Co-authored-by: openhands Reviewed-on: https://codeberg.org/johba/harb/pulls/92 --- AGENTS.md | 18 ++-- CHANGELOG_VERSION_VALIDATION.md | 14 +-- containers/bootstrap.sh | 15 ++- containers/ponder-dev-entrypoint.sh | 2 +- containers/txn-bot-entrypoint.sh | 2 +- containers/webapp-dev-entrypoint.sh | 2 +- podman-compose.yml => docker-compose.yml | 2 +- docs/docker.md | 131 +++++++++++++++++++++++ docs/podman.md | 44 -------- kraiken-lib/AGENTS.md | 2 +- scripts/dev.sh | 69 +++++++----- scripts/watch-kraiken-lib.sh | 8 +- services/ponder/AGENTS.md | 2 +- 13 files changed, 211 insertions(+), 100 deletions(-) rename podman-compose.yml => docker-compose.yml (98%) create mode 100644 docs/docker.md delete mode 100644 docs/podman.md diff --git a/AGENTS.md b/AGENTS.md index 3103000..6a36b25 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,7 +16,8 @@ - `./scripts/dev.sh restart --light` - Fast restart (~10-20s): only webapp + txnbot, preserves Anvil/Ponder state. Use for frontend changes. - `./scripts/dev.sh restart --full` - Full restart (~3-4min): redeploys contracts, fresh state. Use for contract changes. - Supported environments: `BASE_SEPOLIA_LOCAL_FORK` (default Anvil fork), `BASE_SEPOLIA`, and `BASE`. Match contract addresses and RPCs accordingly. -- The stack boots Anvil, deploys contracts, seeds liquidity, starts Ponder, launches the landing site, and runs the txnBot. Wait for logs to settle before manual testing. +- The stack uses Docker containers orchestrated via docker-compose. The script boots Anvil, deploys contracts, seeds liquidity, starts Ponder, launches the landing site, and runs the txnBot. Wait for logs to settle before manual testing. +- **Prerequisites**: Docker Engine (Linux) or Colima (Mac). See installation instructions below. ## Component Guides - `onchain/` - Solidity + Foundry contracts, deploy scripts, and fuzzing helpers ([details](onchain/AGENTS.md)). @@ -38,11 +39,16 @@ - **CI Enforcement**: GitHub workflow validates that contract VERSION is in `COMPATIBLE_CONTRACT_VERSIONS` before merging PRs. - See `VERSION_VALIDATION.md` for complete architecture, workflows, and troubleshooting. -## Podman Orchestration -- **Dependency Management**: `podman-compose.yml` has NO `depends_on` declarations. All service ordering is handled in `scripts/dev.sh` via phased startup with explicit health checks. -- **Why**: Podman's dependency graph validator fails when containers have compose metadata dependencies, causing "container not found in input list" errors even when containers exist. +## Docker Installation & Setup +- **Linux**: Install Docker Engine via package manager or `curl -fsSL https://get.docker.com | sh`, then add user to docker group: `sudo usermod -aG docker $USER` (logout/login required) +- **Mac**: Use Colima (open-source Docker Desktop alternative): + ```bash + brew install colima docker docker-compose + colima start --cpu 4 --memory 8 --disk 100 + docker ps # verify installation + ``` +- **Container Orchestration**: `docker-compose.yml` has NO `depends_on` declarations. All service ordering is handled in `scripts/dev.sh` via phased startup with explicit health checks. - **Startup Phases**: (1) Create all containers, (2) Start anvil+postgres and wait for healthy, (3) Start bootstrap and wait for completion, (4) Start ponder and wait for healthy, (5) Start webapp/landing/txn-bot, (6) Start caddy. -- If you see dependency graph errors, verify `depends_on` was not re-added to `podman-compose.yml`. ## Guardrails & Tips - `token0isWeth` flips amount semantics; confirm ordering before seeding or interpreting liquidity. @@ -51,7 +57,7 @@ - Ponder stores data in `.ponder/`; drop the directory if schema changes break migrations. - Keep git clean before committing; never leave commented-out code or untested changes. - **ES Modules**: The entire stack uses ES modules. kraiken-lib, txnBot, Ponder, and web-app all require `"type": "module"` in package.json and use `import` syntax. -- **kraiken-lib Build**: Run `./scripts/build-kraiken-lib.sh` before `podman-compose up` so containers mount a fresh `kraiken-lib/dist` from the host. +- **kraiken-lib Build**: Run `./scripts/build-kraiken-lib.sh` before `docker-compose up` so containers mount a fresh `kraiken-lib/dist` from the host. - **Live Reload**: `scripts/watch-kraiken-lib.sh` rebuilds on file changes (requires inotify-tools) and restarts dependent containers automatically. ## Code Quality & Git Hooks diff --git a/CHANGELOG_VERSION_VALIDATION.md b/CHANGELOG_VERSION_VALIDATION.md index 12c756a..e9f8f10 100644 --- a/CHANGELOG_VERSION_VALIDATION.md +++ b/CHANGELOG_VERSION_VALIDATION.md @@ -49,12 +49,12 @@ This release implements a comprehensive version validation system to ensure cont - Troubleshooting guide - Maintenance guidelines -### 2. Podman Orchestration Fix +### 2. Container Orchestration Fix -**Problem:** Podman's dependency graph validator fails with "container not found in input list" errors when containers have `depends_on` metadata. +**Problem:** Container dependency graph validator can fail with "container not found in input list" errors when containers have `depends_on` metadata. **Solution:** -- `podman-compose.yml`: Removed ALL `depends_on` declarations from: +- `docker-compose.yml`: Removed ALL `depends_on` declarations from: - bootstrap - ponder - webapp @@ -63,7 +63,7 @@ This release implements a comprehensive version validation system to ensure cont - caddy - `scripts/dev.sh`: Implemented phased startup with explicit health checks: - 1. Create all containers (`podman-compose up --no-start`) + 1. Create all containers (`docker-compose up --no-start`) 2. Start anvil & postgres, wait for healthy 3. Start bootstrap, wait for completion 4. Start ponder, wait for healthy @@ -126,7 +126,7 @@ This release implements a comprehensive version validation system to ensure cont 6. `kraiken-lib/src/taxRates.ts` - Generated tax rates with checksums 7. `kraiken-lib/src/tests/taxRates.test.ts` - Fixed Jest compatibility 8. `onchain/src/Kraiken.sol` - Added VERSION constant -9. `podman-compose.yml` - Removed all depends_on declarations +9. `docker-compose.yml` - Removed all depends_on declarations 10. `scripts/build-kraiken-lib.sh` - Updated build process 11. `scripts/dev.sh` - Implemented phased startup 12. `services/ponder/AGENTS.md` - Updated documentation @@ -193,7 +193,7 @@ This release implements a comprehensive version validation system to ensure cont 6. **Verify version validation:** ```bash - podman logs harb_ponder_1 | grep "version validated" + docker logs harb_ponder_1 | grep "version validated" ``` Should output: `✓ Contract version validated: v1 (kraiken-lib v1)` @@ -237,7 +237,7 @@ When making breaking changes to TAX_RATES, events, or data structures: ### Manual Verification ```bash # Check Ponder logs for version validation -podman logs harb_ponder_1 | grep "version validated" +docker logs harb_ponder_1 | grep "version validated" # Output: ✓ Contract version validated: v1 (kraiken-lib v1) # Check contract VERSION diff --git a/containers/bootstrap.sh b/containers/bootstrap.sh index d41088f..df60002 100755 --- a/containers/bootstrap.sh +++ b/containers/bootstrap.sh @@ -26,7 +26,7 @@ if [[ -n "$GIT_BRANCH" ]]; then fi fi fi -STATE_DIR=$ROOT_DIR/tmp/podman +STATE_DIR=$ROOT_DIR/tmp/containers LOG_DIR=$STATE_DIR/logs SETUP_LOG=$LOG_DIR/setup.log CONTRACT_ENV=$STATE_DIR/contracts.env @@ -177,17 +177,14 @@ seed_application_state() { } prime_chain() { - log "Pre-mining 200 blocks (2x ring buffer warmup)..." - # Try batch mine first (0xc8 = 200 blocks = 2x MINIMUM_BLOCKS_FOR_RING_BUFFER, 0x1 = 1 second interval) - if cast rpc --rpc-url "$ANVIL_RPC" anvil_mine "0xc8" "0x1" >/dev/null 2>&1; then - log "Used batch mining" + log "Pre-mining 5 blocks (minimal warmup for fast Ponder sync)..." + # Mine just 5 blocks - enough for Ponder to have some history but keeps sync fast + if cast rpc --rpc-url "$ANVIL_RPC" anvil_mine "0x5" "0x1" >/dev/null 2>&1; then + log "Mined 5 blocks" else log "Batch mining failed, using individual evm_mine calls" - for i in {1..200}; do + for i in {1..5}; do cast rpc --rpc-url "$ANVIL_RPC" evm_mine >/dev/null 2>&1 || true - if ((i % 50 == 0)); then - log "Mined $i blocks..." - fi done fi log "Pre-mining complete" diff --git a/containers/ponder-dev-entrypoint.sh b/containers/ponder-dev-entrypoint.sh index f59f44e..acc5349 100755 --- a/containers/ponder-dev-entrypoint.sh +++ b/containers/ponder-dev-entrypoint.sh @@ -22,7 +22,7 @@ if [[ -n "$GIT_BRANCH" ]]; then fi fi -CONTRACT_ENV=$ROOT_DIR/tmp/podman/contracts.env +CONTRACT_ENV=$ROOT_DIR/tmp/containers/contracts.env PONDER_WORKDIR=$ROOT_DIR/services/ponder while [[ ! -f "$CONTRACT_ENV" ]]; do diff --git a/containers/txn-bot-entrypoint.sh b/containers/txn-bot-entrypoint.sh index f4a6416..6f7c29f 100755 --- a/containers/txn-bot-entrypoint.sh +++ b/containers/txn-bot-entrypoint.sh @@ -22,7 +22,7 @@ if [[ -n "$GIT_BRANCH" ]]; then fi fi -TXNBOT_ENV_FILE=$ROOT_DIR/tmp/podman/txnBot.env +TXNBOT_ENV_FILE=$ROOT_DIR/tmp/containers/txnBot.env BOT_DIR=$ROOT_DIR/services/txnBot REQUIRED_DIST=$ROOT_DIR/kraiken-lib/dist/index.js diff --git a/containers/webapp-dev-entrypoint.sh b/containers/webapp-dev-entrypoint.sh index d036a03..4ce683f 100755 --- a/containers/webapp-dev-entrypoint.sh +++ b/containers/webapp-dev-entrypoint.sh @@ -22,7 +22,7 @@ if [[ -n "$GIT_BRANCH" ]]; then fi fi -CONTRACT_ENV=$ROOT_DIR/tmp/podman/contracts.env +CONTRACT_ENV=$ROOT_DIR/tmp/containers/contracts.env APP_DIR=$ROOT_DIR/web-app SWAP_ROUTER=0x94cC0AaC535CCDB3C01d6787D6413C739ae12bc4 diff --git a/podman-compose.yml b/docker-compose.yml similarity index 98% rename from podman-compose.yml rename to docker-compose.yml index cd67b45..c972c2d 100644 --- a/podman-compose.yml +++ b/docker-compose.yml @@ -57,7 +57,7 @@ services: - harb-network restart: "no" healthcheck: - test: ["CMD", "test", "-f", "/workspace/tmp/podman/contracts.env"] + test: ["CMD", "test", "-f", "/workspace/tmp/containers/contracts.env"] interval: 5s retries: 18 start_period: 10s diff --git a/docs/docker.md b/docs/docker.md new file mode 100644 index 0000000..78c11de --- /dev/null +++ b/docs/docker.md @@ -0,0 +1,131 @@ +# Docker Development Environment + +The Docker stack powers `scripts/dev.sh` using containerized services. Every boot spins up a fresh Base Sepolia fork, redeploys contracts, seeds liquidity, and launches the live-reload services behind Caddy on port 8081. + +## Service Topology +- `anvil` – Base Sepolia fork with optional mnemonic from `onchain/.secret.local` +- `bootstrap` – one-shot job running `DeployLocal.sol`, seeding liquidity, priming blocks, and writing shared env files +- `ponder` – `npm run dev` for the indexer (port 42069 inside the pod) +- `frontend` – Vite dev server for `web-app` (port 5173 inside the pod) +- `txn-bot` – automation loop plus Express status API (port 43069 inside the pod) +- `caddy` – front door at `http://:80`, routing `/api/graphql`, `/health`, `/api/rpc`, and `/api/txn` to the internal services + +All containers mount the repository so code edits hot-reload exactly as the local script. Named volumes keep `node_modules` caches between restarts. + +## Prerequisites + +### Linux +```bash +# Install Docker Engine +curl -fsSL https://get.docker.com | sh +sudo usermod -aG docker $USER +# Logout and login again for group changes to take effect +``` + +### Mac +```bash +# Install Colima (open-source Docker Desktop alternative) +brew install colima docker docker-compose + +# Start Colima VM with recommended resources +colima start --cpu 4 --memory 8 --disk 100 + +# Verify installation +docker ps +``` + +## Launching + +**Recommended**: Use the helper script +```bash +./scripts/dev.sh start +``` + +This will: +1. Build kraiken-lib +2. Start Anvil (Base Sepolia fork) +3. Deploy contracts via bootstrap +4. Start Ponder (indexes events) +5. Start web-app, landing, txn-bot +6. Start Caddy reverse proxy on port 8081 + +**Startup time**: ~6 minutes on first run (includes Ponder indexing 300+ blocks) + +**Manual approach** (not recommended): +```bash +docker compose up -d +``` + +**Stopping the stack:** +```bash +./scripts/dev.sh stop +# or +docker compose down +``` + +**Quick restarts for development:** +- `./scripts/dev.sh restart --light` - Fast restart (~10-20s): only webapp + txnbot, preserves Anvil/Ponder state. **Use for frontend changes.** +- `./scripts/dev.sh restart --full` - Full restart (~6 min): redeploys contracts, fresh state. **Use for contract changes.** + +**Important**: Every full restart redeploys contracts and rewrites `services/ponder/.env.local` and `tmp/containers/txnBot.env`. + +### Access Points (via Caddy on port 8081) + +**For reviewing code changes in your browser:** +- Landing page: `http://localhost:8081/` (marketing site) +- Web-app: `http://localhost:8081/app/` (staking interface - **use this for testing**) +- GraphQL Playground: `http://localhost:8081/api/graphql` +- TxnBot status: `http://localhost:8081/api/txn/status` + +**Direct RPC access:** +- Anvil RPC: `http://localhost:8081/api/rpc` (or `http://localhost:8545` directly) + +**Hot reload workflow:** +1. Start stack: `./scripts/dev.sh start` +2. Open `http://localhost:8081/app/` in your browser +3. Edit files in `web-app/src/` - changes appear instantly (Vite HMR) +4. Edit files in `landing/src/` - changes appear on `http://localhost:8081/` +5. Edit smart contracts in `onchain/src/` - requires `./scripts/dev.sh restart --full` + +## Configuration Knobs +Set environment variables before `docker-compose up`: +- `FORK_URL` – Anvil upstream RPC (defaults to `https://sepolia.base.org`) +- `DEPLOYER_PK`, `DEPLOYER_ADDR` – override deployer wallet; otherwise derived from `.secret.local` or Foundry defaults +- `TXNBOT_PRIVATE_KEY`, `TXNBOT_ADDRESS`, `TXNBOT_FUND_VALUE` – customise bot signer and funding + +Edit `containers/Caddyfile` if you need different routes or ports. + +## Known Limitations +- State is ephemeral; every restart wipes the fork and redeploys contracts. +- Processes run in dev/watch mode (`npm run dev`), so staging traffic is not production hardened. +- Secrets live in env files inside the repo mount because no external secret store is wired in. + +## Troubleshooting + +### Mac: "Cannot connect to Docker daemon" +```bash +# Ensure Colima is running +colima status +colima start + +# Verify Docker can connect +docker ps +``` + +### Permission errors on Linux +```bash +# Add your user to the docker group +sudo usermod -aG docker $USER + +# Logout and login again, or use: +newgrp docker +``` + +### Port conflicts +If you see "port already in use" errors: +```bash +# Check what's using the port +lsof -i :8081 # or :8545, :5173, etc. + +# Stop conflicting services or change ports in docker-compose.yml +``` diff --git a/docs/podman.md b/docs/podman.md deleted file mode 100644 index 6f988be..0000000 --- a/docs/podman.md +++ /dev/null @@ -1,44 +0,0 @@ -# Podman Staging Environment - -The Podman stack mirrors `scripts/dev.sh` using long-lived containers. Every boot spins up a fresh Base Sepolia fork, redeploys contracts, seeds liquidity, and launches the live-reload services behind Caddy on port 80. - -## Service Topology -- `anvil` – Base Sepolia fork with optional mnemonic from `onchain/.secret.local` -- `bootstrap` – one-shot job running `DeployLocal.sol`, seeding liquidity, priming blocks, and writing shared env files -- `ponder` – `npm run dev` for the indexer (port 42069 inside the pod) -- `frontend` – Vite dev server for `web-app` (port 5173 inside the pod) -- `txn-bot` – automation loop plus Express status API (port 43069 inside the pod) -- `caddy` – front door at `http://:80`, routing `/api/graphql`, `/health`, `/api/rpc`, and `/api/txn` to the internal services - -All containers mount the repository so code edits hot-reload exactly as the local script. Named volumes keep `node_modules` caches between restarts. - -## Prerequisites -- Podman 4.x (rootless recommended) -- `podman-compose` - -## Launching -```bash -podman-compose -f podman-compose.yml build -podman-compose -f podman-compose.yml up -``` -- First run takes several minutes while Foundry installs deps, deploys contracts, and runs the seeding transactions. -- Use `podman-compose down` to stop. Bring-up always redeploys and rewrites `services/ponder/.env.local` plus `tmp/podman/txnBot.env`. - -### Access Points (via Caddy) -- Frontend: `http:///` -- GraphQL: `http:///api/graphql` -- RPC passthrough: `http:///api/rpc` -- Txn bot status: `http:///api/txn/status` - -## Configuration Knobs -Set environment variables before `podman-compose up`: -- `FORK_URL` – Anvil upstream RPC (defaults to `https://sepolia.base.org`) -- `DEPLOYER_PK`, `DEPLOYER_ADDR` – override deployer wallet; otherwise derived from `.secret.local` or Foundry defaults -- `TXNBOT_PRIVATE_KEY`, `TXNBOT_ADDRESS`, `TXNBOT_FUND_VALUE` – customise bot signer and funding - -Edit `containers/Caddyfile` if you need different routes or ports. - -## Known Limitations -- State is ephemeral; every restart wipes the fork and redeploys contracts. -- Processes run in dev/watch mode (`npm run dev`), so staging traffic is not production hardened. -- Secrets live in env files inside the repo mount because no external secret store is wired in. diff --git a/kraiken-lib/AGENTS.md b/kraiken-lib/AGENTS.md index 9f75e5c..495565d 100644 --- a/kraiken-lib/AGENTS.md +++ b/kraiken-lib/AGENTS.md @@ -42,7 +42,7 @@ Shared TypeScript helpers used by the landing app, txnBot, and other services to - `"moduleResolution": "node"` - Enable proper module resolution - `"rootDir": "./src"` - Ensure flat output structure in `dist/` - **Build Output**: Running `npx tsc` produces ES module `.js` files in `dist/` that can be consumed by both browser (Vite) and Node.js (≥14 with `"type": "module"`). -- **Container Mount**: Podman/Docker services now bind-mount `dist/` read-only from the host. Run `./scripts/build-kraiken-lib.sh` before `podman-compose up` or keep `scripts/watch-kraiken-lib.sh` running to rebuild automatically. +- **Container Mount**: Docker services bind-mount `dist/` read-only from the host. Run `./scripts/build-kraiken-lib.sh` before `docker-compose up` or keep `scripts/watch-kraiken-lib.sh` running to rebuild automatically. ## Quality Guidelines - Keep helpers pure and side-effect free; they should accept explicit dependencies. diff --git a/scripts/dev.sh b/scripts/dev.sh index 5152617..580d89a 100755 --- a/scripts/dev.sh +++ b/scripts/dev.sh @@ -4,17 +4,33 @@ set -euo pipefail cd "$(dirname "$0")/.." # Timeout constants (in seconds) -readonly ANVIL_TIMEOUT=30 # Anvil starts fast -readonly POSTGRES_TIMEOUT=20 # Database init is quick -readonly BOOTSTRAP_TIMEOUT=60 # Contract deployment + seeding -readonly PONDER_TIMEOUT=90 # Must index bootstrap events -readonly WEBAPP_TIMEOUT=90 # npm install + Vite startup -readonly CADDY_TIMEOUT=10 # Proxy starts instantly +readonly ANVIL_TIMEOUT=60 # Anvil starts fast (increased for first-time setup) +readonly POSTGRES_TIMEOUT=30 # Database init is quick +readonly BOOTSTRAP_TIMEOUT=120 # Contract deployment + seeding +readonly PONDER_TIMEOUT=120 # Must index bootstrap events +readonly WEBAPP_TIMEOUT=120 # npm install + Vite startup +readonly CADDY_TIMEOUT=20 # Proxy starts instantly readonly POLL_INTERVAL=2 # Check health every N seconds PID_FILE=/tmp/kraiken-watcher.pid PROJECT_NAME=${COMPOSE_PROJECT_NAME:-$(basename "$PWD")} +# Detect container runtime +if command -v docker compose &> /dev/null; then + COMPOSE_CMD="docker compose" + RUNTIME_CMD="docker" +elif command -v docker-compose &> /dev/null; then + COMPOSE_CMD="docker-compose" + RUNTIME_CMD="docker" +else + echo "Error: docker/docker-compose not found. Please install Docker." + echo "" + echo "Installation instructions:" + echo " Linux: https://docs.docker.com/engine/install/" + echo " Mac: brew install colima docker docker-compose && colima start" + exit 1 +fi + container_name() { local service="$1" echo "${PROJECT_NAME}_${service}_1" @@ -28,13 +44,13 @@ cleanup_existing() { # Remove PID file rm -f "$PID_FILE" - # Kill zombie podman processes - pkill -9 -f "podman wait.*${PROJECT_NAME}_" 2>/dev/null || true + # Kill zombie container processes + pkill -9 -f "${RUNTIME_CMD} wait.*${PROJECT_NAME}_" 2>/dev/null || true # Remove any existing containers (suppress errors if they don't exist) echo " Cleaning up existing containers..." - podman ps -a --filter "label=com.docker.compose.project=${PROJECT_NAME}" --format "{{.Names}}" 2>/dev/null | \ - xargs -r podman rm -f 2>&1 | grep -v "Error.*no container" || true + ${RUNTIME_CMD} ps -a --filter "label=com.docker.compose.project=${PROJECT_NAME}" --format "{{.Names}}" 2>/dev/null | \ + xargs -r ${RUNTIME_CMD} rm -f 2>&1 | grep -v "Error.*no container" || true } # Wait for container to be healthy (via healthcheck) @@ -45,7 +61,10 @@ wait_for_healthy() { local start_time=$(date +%s) for i in $(seq 1 "$max_attempts"); do - if podman healthcheck run "$container" &>/dev/null; then + # Docker doesn't have a standalone healthcheck command, check via inspect + local health_status + health_status=$(${RUNTIME_CMD} inspect --format='{{.State.Health.Status}}' "$container" 2>/dev/null || echo "unknown") + if [[ "$health_status" == "healthy" ]]; then local elapsed=$(($(date +%s) - start_time)) echo " ✓ $container ready (${elapsed}s)" return 0 @@ -66,7 +85,7 @@ wait_for_exited() { for i in $(seq 1 "$max_attempts"); do local status - status=$(podman inspect "$container" --format='{{.State.Status}}' 2>/dev/null || echo "unknown") + status=$(${RUNTIME_CMD} inspect "$container" --format='{{.State.Status}}' 2>/dev/null || echo "unknown") if [[ "$status" == "exited" ]]; then local elapsed=$(($(date +%s) - start_time)) echo " ✓ $container completed (${elapsed}s)" @@ -97,32 +116,32 @@ start_stack() { # Phase 1: Start base services (no dependencies) echo " Starting anvil & postgres..." - podman-compose up -d anvil postgres 2>&1 | grep -v "STEP\|Copying\|Writing\|Getting\|fetch\|Installing\|Executing" || true + ${COMPOSE_CMD} up -d anvil postgres 2>&1 | grep -v "STEP\|Copying\|Writing\|Getting\|fetch\|Installing\|Executing" || true wait_for_healthy "$(container_name anvil)" "$ANVIL_TIMEOUT" || exit 1 wait_for_healthy "$(container_name postgres)" "$POSTGRES_TIMEOUT" || exit 1 # Phase 2: Start bootstrap (depends on anvil & postgres healthy) echo " Starting bootstrap..." - podman-compose up -d bootstrap >/dev/null 2>&1 + ${COMPOSE_CMD} up -d bootstrap >/dev/null 2>&1 wait_for_exited "$(container_name bootstrap)" "$BOOTSTRAP_TIMEOUT" || exit 1 # Phase 3: Start ponder (depends on bootstrap completed) echo " Starting ponder..." - podman-compose up -d ponder >/dev/null 2>&1 + ${COMPOSE_CMD} up -d ponder >/dev/null 2>&1 wait_for_healthy "$(container_name ponder)" "$PONDER_TIMEOUT" || exit 1 # Phase 4: Start frontend services (depend on ponder healthy) echo " Starting webapp, landing, txn-bot..." - podman-compose up -d webapp landing txn-bot >/dev/null 2>&1 + ${COMPOSE_CMD} up -d webapp landing txn-bot >/dev/null 2>&1 wait_for_healthy "$(container_name webapp)" "$WEBAPP_TIMEOUT" || exit 1 # Phase 5: Start caddy (depends on frontend services) echo " Starting caddy..." - podman-compose up -d caddy >/dev/null 2>&1 + ${COMPOSE_CMD} up -d caddy >/dev/null 2>&1 wait_for_healthy "$(container_name caddy)" "$CADDY_TIMEOUT" || exit 1 @@ -142,7 +161,7 @@ start_stack() { stop_stack() { cleanup_existing - podman-compose down + ${COMPOSE_CMD} down echo "[ok] Stack stopped" } @@ -151,7 +170,7 @@ check_health() { local services=(anvil postgres ponder webapp landing txn-bot caddy) for service in "${services[@]}"; do local container - container=$(podman ps --all \ + container=$(${RUNTIME_CMD} ps --all \ --filter "label=com.docker.compose.project=${PROJECT_NAME}" \ --filter "label=com.docker.compose.service=${service}" \ --format '{{.Names}}' | head -n1) @@ -161,7 +180,9 @@ check_health() { continue fi - if podman healthcheck run "$container" &>/dev/null; then + local health_status + health_status=$(${RUNTIME_CMD} inspect --format='{{.State.Health.Status}}' "$container" 2>/dev/null || echo "unknown") + if [[ "$health_status" == "healthy" ]]; then echo " [ok] $service" else echo " [!!] $service" @@ -174,12 +195,12 @@ restart_light() { echo " Preserving Anvil state (contracts remain deployed)" local webapp_container txnbot_container - webapp_container=$(podman ps --all \ + webapp_container=$(${RUNTIME_CMD} ps --all \ --filter "label=com.docker.compose.project=${PROJECT_NAME}" \ --filter "label=com.docker.compose.service=webapp" \ --format '{{.Names}}' | head -n1) - txnbot_container=$(podman ps --all \ + txnbot_container=$(${RUNTIME_CMD} ps --all \ --filter "label=com.docker.compose.project=${PROJECT_NAME}" \ --filter "label=com.docker.compose.service=txn-bot" \ --format '{{.Names}}' | head -n1) @@ -192,8 +213,8 @@ restart_light() { local start_time=$(date +%s) echo " Restarting containers..." - podman restart "$webapp_container" >/dev/null - [[ -n "$txnbot_container" ]] && podman restart "$txnbot_container" >/dev/null + ${RUNTIME_CMD} restart "$webapp_container" >/dev/null + [[ -n "$txnbot_container" ]] && ${RUNTIME_CMD} restart "$txnbot_container" >/dev/null echo " Waiting for webapp to be ready..." local max_attempts=30 diff --git a/scripts/watch-kraiken-lib.sh b/scripts/watch-kraiken-lib.sh index 7d2d62b..6c20e83 100755 --- a/scripts/watch-kraiken-lib.sh +++ b/scripts/watch-kraiken-lib.sh @@ -10,8 +10,8 @@ if ! command -v inotifywait >/dev/null 2>&1; then exit 1 fi -if ! command -v podman >/dev/null 2>&1; then - echo "Error: podman not found on PATH." >&2 +if ! command -v docker >/dev/null 2>&1; then + echo "Error: docker not found on PATH." >&2 exit 1 fi @@ -20,7 +20,7 @@ cd "$ROOT_DIR" restart_services() { local missing=0 local running - mapfile -t running < <(podman ps --format '{{.Names}}') + mapfile -t running < <(docker ps --format '{{.Names}}') for service in "${SERVICES[@]}"; do local found=1 @@ -37,7 +37,7 @@ restart_services() { continue fi - if ! podman restart "$service" >/dev/null; then + if ! docker restart "$service" >/dev/null; then echo "Warning: failed to restart $service" >&2 missing=1 fi diff --git a/services/ponder/AGENTS.md b/services/ponder/AGENTS.md index f5c6f07..ef241b5 100644 --- a/services/ponder/AGENTS.md +++ b/services/ponder/AGENTS.md @@ -16,7 +16,7 @@ Ponder-based indexer that records Kraiken protocol activity and exposes the Grap ## Development Workflow - Primary path: `nohup ./scripts/dev.sh start &` boots Anvil, deploys contracts, and launches Ponder in watch mode. -- Podman stack: `podman-compose up -d` starts all services including PostgreSQL; bootstrap creates `.env.local` automatically. +- Docker stack: `docker-compose up -d` starts all services including PostgreSQL; bootstrap creates `.env.local` automatically. - Focused debugging: within `services/ponder/`, run `npm install` then `PONDER_NETWORK=BASE_SEPOLIA_LOCAL_FORK npm run dev` once the stack is already online. - For production-style runs, use `npm run build` followed by `PONDER_NETWORK=BASE npm run start` and point `DATABASE_URL` to PostgreSQL if persistence is required.