migrate/podman-to-docker (#92)
podman to docker Co-authored-by: openhands <openhands@all-hands.dev> Reviewed-on: https://codeberg.org/johba/harb/pulls/92
This commit is contained in:
parent
c2720c35a5
commit
5d71753086
13 changed files with 211 additions and 100 deletions
18
AGENTS.md
18
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
131
docs/docker.md
Normal file
131
docs/docker.md
Normal file
|
|
@ -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://<host>: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
|
||||
```
|
||||
|
|
@ -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://<host>: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://<host>/`
|
||||
- GraphQL: `http://<host>/api/graphql`
|
||||
- RPC passthrough: `http://<host>/api/rpc`
|
||||
- Txn bot status: `http://<host>/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.
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue