mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-24 09:50:01 +00:00
## 🎯 Overview This PR introduces a comprehensive Docker Compose configuration for running a complete local DataHaven network, making it significantly easier for developers to spin up and test the entire stack locally. ## 🏗️ Architecture ```mermaid graph TB subgraph "DataHaven Network (Docker)" subgraph "Consensus Layer" Alice["🔷 Alice (Validator)<br/>:9944 RPC<br/>4 Keys: GRAN, BABE, IMON, BEEF"] Bob["🔷 Bob (Validator)<br/>:9945 RPC<br/>4 Keys: GRAN, BABE, IMON, BEEF"] Alice <-->|P2P/mDNS| Bob end subgraph "Storage Provider Layer" MSP["💾 MSP (Charlie)<br/>:9946 RPC<br/>1 GiB Storage<br/>1 Key: BCSV"] BSP01["💾 BSP01 (Dave)<br/>:9947 RPC<br/>1 GiB Storage<br/>1 Key: BCSV"] BSP02["💾 BSP02 (Eve)<br/>:9948 RPC<br/>1 GiB Storage<br/>1 Key: BCSV"] end subgraph "Monitoring Layer" Indexer["📊 Indexer<br/>:9949 RPC<br/>Full Mode<br/>No Keys"] Fisherman["🎣 Fisherman (Gustavo)<br/>:9950 RPC<br/>Storage Monitor<br/>1 Key: BCSV"] DB["🗄️ PostgreSQL<br/>:5432<br/>indexer/datahaven"] end Alice -.->|Syncs| MSP Bob -.->|Syncs| MSP Alice -.->|Syncs| BSP01 Bob -.->|Syncs| BSP02 Alice -.->|Syncs| Indexer Bob -.->|Syncs| Fisherman MSP -.->|Monitors| Fisherman BSP01 -.->|Monitors| Fisherman BSP02 -.->|Monitors| Fisherman Indexer -->|Writes| DB Fisherman -->|Writes| DB end style Alice fill:#4a90e2,stroke:#2e5c8a,color:#fff style Bob fill:#4a90e2,stroke:#2e5c8a,color:#fff style MSP fill:#50c878,stroke:#2d7a4a,color:#fff style BSP01 fill:#50c878,stroke:#2d7a4a,color:#fff style BSP02 fill:#50c878,stroke:#2d7a4a,color:#fff style Indexer fill:#f5a623,stroke:#b87818,color:#fff style Fisherman fill:#f5a623,stroke:#b87818,color:#fff style DB fill:#9b59b6,stroke:#6c3a82,color:#fff ``` **Legend:** - 🔷 Validators - Consensus and block production - 💾 Storage Providers - File storage and retrieval - 📊 Indexer - Full blockchain indexing - 🎣 Fisherman - Storage provider monitoring - 🗄️ PostgreSQL - Database for indexer/fisherman - `<-->` P2P Communication | `-.->` Network Sync | `-->` Database Connection ## ✨ What's Included ### Core Network (8 Services) - **2 Validator Nodes** (Alice & Bob) - Consensus and block production - **1 Main Storage Provider (MSP)** - Charlie with 1 GiB storage capacity - **2 Backup Storage Providers (BSPs)** - Dave and Eve with 1 GiB each - **1 StorageHub Indexer** - Full blockchain indexer with PostgreSQL - **1 Fisherman Node** - Gustavo monitoring storage provider behavior - **1 PostgreSQL Database** - Shared database for indexer and fisherman ### Key Features ✅ **Automated Key Injection** - All validator and storage provider keys automatically injected on startup ✅ **Health Checks** - Validators have health checks that verify RPC port is listening before dependent services start ✅ **Orchestrated Startup** - Services start in correct order with health-based dependencies ✅ **Persistent Storage** - Chain data, keystores, and database all persisted in Docker volumes ✅ **Unified Entrypoint Script** - Single script handles all node types (validator, MSP, BSP, fisherman) ✅ **Proper User Permissions** - Root for setup, switches to datahaven user for node execution ✅ **mDNS Peer Discovery** - Nodes automatically discover each other on the Docker network ✅ **Comprehensive Documentation** - Full setup guide, troubleshooting, and verification steps ### 🔄 Startup Sequence The network starts in a carefully orchestrated sequence to ensure stability: 1. **Alice (Validator)** starts first - Injects 4 keys (GRAN, BABE, IMON, BEEF) - Health check waits for RPC port 9944 to be listening - Uses `/proc/net/tcp` for minimal-dependency port checking 2. **Bob (Validator)** waits for Alice to be healthy - Ensures at least one validator is fully operational - Enables block production to start immediately 3. **Storage Providers & Monitoring** wait for both validators to be healthy - MSP, BSP01, BSP02 start after validators are ready - Indexer and Fisherman wait for validators before syncing - PostgreSQL starts independently with its own health check This dependency chain prevents race conditions and ensures reliable network formation. ## 🚀 Quick Start ```bash cd operator # Build the binary (development mode with fast blocks) ./scripts/docker-prepare.sh --fast # Start the entire network docker-compose up -d # View logs docker-compose logs -f # Check service health docker-compose ps # Stop the network docker-compose down -v ``` ## 📋 Port Mappings | Service | RPC/WebSocket | Prometheus | P2P | Database/API | |---------|---------------|------------|-----|--------------| | Alice | 9944 | 9615 | 30333 | - | | Bob | 9945 | 9616 | 30334 | - | | MSP | 9946 | 9617 | 30335 | - | | BSP01 | 9947 | 9618 | 30336 | - | | BSP02 | 9948 | 9619 | 30337 | - | | Indexer | 9949 | 9620 | 30338 | - | | Fisherman | 9950 | 9621 | 30339 | - | | PostgreSQL | - | - | - | 5432 | ## 🔑 Key Injection All cryptographic keys are automatically injected on startup: **Validators (Alice & Bob)** - 4 keys each: - GRANDPA (ed25519) - Finality - BABE (sr25519) - Block authoring - ImOnline (sr25519) - Heartbeat - BEEFY (ecdsa) - Bridge consensus **Storage Providers (MSP, BSPs, Fisherman)** - 1 key each: - BCSV (ecdsa) - Storage provider identity **Indexer** - No keys required (non-validating node) ## 🩺 Health Checks Validator nodes (Alice & Bob) implement health checks to ensure proper startup sequencing: **Health Check Method:** - Reads `/proc/net/tcp` directly to check if RPC port is listening - Zero dependencies - works in minimal debian:stable-slim containers - Converts port to hex and searches for LISTEN state (0A) **Configuration:** - Start period: 30s (allows node initialization) - Interval: 10s (check every 10 seconds) - Timeout: 5s (per health check) - Retries: 5 (must pass 5 consecutive checks) **Benefits:** - Prevents dependent services from starting before validators are ready - Eliminates race conditions during network formation - No additional packages required in Docker image ## 🍎 macOS Requirement **Important:** On Docker Desktop for macOS, you must use the **experimental DockerVMM** virtualization framework: 1. Open Docker Desktop settings 2. Go to "General" tab 3. Enable "Use experimental virtualization framework (DockerVMM)" 4. Restart Docker Desktop The default Apple Virtualization Framework causes networking issues with P2P connections. ## 📁 Files Changed - `operator/docker-compose.yml` - Main orchestration configuration - `operator/scripts/docker-entrypoint.sh` - Unified key injection script - `operator/scripts/docker-prepare.sh` - Binary build helper - `operator/scripts/docker-healthcheck.sh` - Health check script for validators - `operator/DOCKER-COMPOSE.md` - Comprehensive documentation ## 🔍 Testing The configuration has been tested on: - ✅ Docker Desktop for macOS (with DockerVMM) - ✅ Docker on Linux/Ubuntu All nodes successfully: - Inject required keys - Pass health checks - Discover peers via mDNS - Sync blocks and finalize - Connect to PostgreSQL database (indexer/fisherman) ## 📝 Notes - All settings are configured for **local development only** - Uses well-known test seed phrase (⚠️ never use in production!) - RPC exposed without authentication - Unsafe flags enabled for convenience --------- Co-authored-by: Claude <noreply@anthropic.com>
341 lines
12 KiB
Markdown
341 lines
12 KiB
Markdown
# Docker Compose Setup for DataHaven Network
|
|
|
|
This docker-compose configuration runs a local DataHaven network with:
|
|
- **2 Validator nodes**: Alice and Bob
|
|
- **1 Main Storage Provider (MSP)** node: Charlie (exposed as "msp")
|
|
- **2 Backup Storage Provider (BSP)** nodes: Dave (bsp01) and Eve (bsp02)
|
|
- **1 StorageHub Indexer** node: Full indexer with PostgreSQL database
|
|
- **1 Fisherman** node: Gustavo - monitors and validates storage providers
|
|
- **1 PostgreSQL database**: Shared database for indexer and fisherman
|
|
|
|
## Prerequisites
|
|
|
|
- Docker & Docker Compose installed
|
|
- Pre-built DataHaven binary (see Building section)
|
|
|
|
## Directory Structure
|
|
|
|
```
|
|
operator/
|
|
├── docker-compose.yml # Main compose configuration
|
|
├── Dockerfile # Node image
|
|
├── scripts/
|
|
│ ├── docker-entrypoint.sh # Unified key injection entrypoint
|
|
│ └── docker-prepare.sh # Build preparation script
|
|
└── DOCKER-COMPOSE.md # This file
|
|
```
|
|
|
|
## Building the Binary
|
|
|
|
Before running docker-compose, you need to build the DataHaven node binary.
|
|
|
|
### Option 1: Using the prepare script (Recommended)
|
|
|
|
```bash
|
|
# For development (faster blocks with fast-runtime feature)
|
|
./scripts/docker-prepare.sh --fast
|
|
|
|
# For production
|
|
./scripts/docker-prepare.sh
|
|
```
|
|
|
|
### Option 2: Manual build
|
|
|
|
```bash
|
|
# For development (faster blocks with fast-runtime feature)
|
|
cargo build --release --features fast-runtime
|
|
|
|
# For production
|
|
cargo build --release
|
|
|
|
# Copy binary to expected location
|
|
mkdir -p build
|
|
cp target/release/datahaven-node build/
|
|
```
|
|
|
|
The binary will be output to `target/release/datahaven-node` and copied to `build/datahaven-node`.
|
|
|
|
## Running the Network
|
|
|
|
Once the binary is built and copied, start the network:
|
|
|
|
```bash
|
|
# Start both validators
|
|
docker-compose up -d
|
|
|
|
# View logs
|
|
docker-compose logs -f
|
|
|
|
# View logs for specific node
|
|
docker-compose logs -f alice
|
|
docker-compose logs -f bob
|
|
docker-compose logs -f msp
|
|
docker-compose logs -f bsp01
|
|
docker-compose logs -f bsp02
|
|
docker-compose logs -f postgres
|
|
docker-compose logs -f indexer
|
|
docker-compose logs -f fisherman
|
|
```
|
|
|
|
### Key Injection
|
|
|
|
All nodes automatically inject the required keys on startup using the unified `docker-entrypoint.sh` script.
|
|
|
|
#### Validator Keys (Alice, Bob)
|
|
Validators require 4 keys:
|
|
1. **GRANDPA** (`gran`) - ed25519 - Finality gadget
|
|
2. **BABE** (`babe`) - sr25519 - Block authoring
|
|
3. **ImOnline** (`imon`) - sr25519 - Validator heartbeat
|
|
4. **BEEFY** (`beef`) - ecdsa - Bridge consensus
|
|
|
|
#### Storage Provider Keys (MSP/BSP)
|
|
Storage providers (both MSP and BSP) require 1 key:
|
|
1. **BCSV** (`bcsv`) - ecdsa - Storage provider identity
|
|
|
|
#### Fisherman Keys
|
|
Fisherman nodes require 1 key:
|
|
1. **BCSV** (`bcsv`) - ecdsa - Storage provider identity
|
|
|
|
Keys are derived from a test seed phrase using the pattern: `<seed>//<NodeName>` (e.g., `//Alice`, `//Bob`, `//Charlie`, `//Dave`, `//Eve`, `//Gustavo`).
|
|
|
|
**⚠️ Security Warning**: The default seed phrase is for **development only**. Never use this in production! To use custom seeds, modify the `SEED` environment variable in `docker-compose.yml`.
|
|
|
|
## Accessing the Nodes
|
|
|
|
All nodes are accessible on the following ports:
|
|
|
|
### Alice (Primary Validator)
|
|
- **WebSocket/RPC**: `ws://localhost:9944`
|
|
- **Prometheus Metrics**: `http://localhost:9615`
|
|
- **P2P**: `localhost:30333`
|
|
|
|
### Bob (Secondary Validator)
|
|
- **WebSocket/RPC**: `ws://localhost:9945`
|
|
- **Prometheus Metrics**: `http://localhost:9616`
|
|
- **P2P**: `localhost:30334`
|
|
|
|
### MSP (Main Storage Provider - Charlie)
|
|
- **WebSocket/RPC**: `ws://localhost:9946`
|
|
- **Prometheus Metrics**: `http://localhost:9617`
|
|
- **P2P**: `localhost:30335`
|
|
- **Storage Capacity**: 1 GiB
|
|
- **Jump Capacity**: 100 MiB
|
|
- **Charging Period**: 100 blocks
|
|
|
|
### BSP01 (Backup Storage Provider - Dave)
|
|
- **WebSocket/RPC**: `ws://localhost:9947`
|
|
- **Prometheus Metrics**: `http://localhost:9618`
|
|
- **P2P**: `localhost:30336`
|
|
- **Storage Capacity**: 1 GiB
|
|
- **Jump Capacity**: 100 MiB
|
|
|
|
### BSP02 (Backup Storage Provider - Eve)
|
|
- **WebSocket/RPC**: `ws://localhost:9948`
|
|
- **Prometheus Metrics**: `http://localhost:9619`
|
|
- **P2P**: `localhost:30337`
|
|
- **Storage Capacity**: 1 GiB
|
|
- **Jump Capacity**: 100 MiB
|
|
|
|
### PostgreSQL Database
|
|
- **Host**: `localhost:5432`
|
|
- **Database**: `datahaven`
|
|
- **Username**: `indexer`
|
|
- **Password**: `indexer`
|
|
- **Connection String**: `postgresql://indexer:indexer@localhost:5432/datahaven`
|
|
|
|
### Indexer (StorageHub Indexer)
|
|
- **WebSocket/RPC**: `ws://localhost:9949`
|
|
- **Prometheus Metrics**: `http://localhost:9620`
|
|
- **P2P**: `localhost:30338`
|
|
- **Mode**: Full indexer with database persistence
|
|
|
|
### Fisherman (Storage Provider Monitor - Gustavo)
|
|
- **WebSocket/RPC**: `ws://localhost:9950`
|
|
- **Prometheus Metrics**: `http://localhost:9621`
|
|
- **P2P**: `localhost:30339`
|
|
- **Role**: Monitors and validates storage provider behavior
|
|
|
|
## Network Communication
|
|
|
|
All nodes run on a shared Docker network (`datahaven-network`). All nodes use:
|
|
- `--discover-local` for automatic peer discovery via mDNS
|
|
- `--unsafe-force-node-key-generation` for automatic node key generation
|
|
|
|
The validators (Alice and Bob) will produce blocks, while the storage providers (MSP and BSPs) provide storage services.
|
|
|
|
**Note**: All nodes use libp2p as the network backend (`--network-backend=libp2p`).
|
|
|
|
### Docker Desktop for macOS
|
|
**Important**: On Docker Desktop for macOS, you must use the **experimental DockerVMM** virtualization framework for proper networking support.
|
|
|
|
To enable DockerVMM:
|
|
1. Open Docker Desktop settings
|
|
2. Go to "General" tab
|
|
3. Enable "Use experimental virtualization framework (DockerVMM)"
|
|
4. Restart Docker Desktop
|
|
|
|
**Note**: The default Apple Virtualization Framework will cause networking issues with peer-to-peer connections, resulting in connection failures and protocol handshake errors.
|
|
|
|
## Stopping the Network
|
|
|
|
```bash
|
|
# Stop all nodes
|
|
docker-compose down
|
|
|
|
# Stop and remove volumes (clears chain data)
|
|
docker-compose down -v
|
|
```
|
|
|
|
## Configuration Notes
|
|
|
|
### Node Flags
|
|
- `--chain=stagenet-local` - Use stagenet-local chain specification (ensures all nodes share same genesis)
|
|
- `--base-path=/data` - Base directory for chain data and keystore
|
|
- `--keystore-path=/data/keystore` - Keystore persisted in Docker volumes
|
|
- `--validator` - Enables validator mode (Alice & Bob only)
|
|
- `--pool-type=fork-aware` - Uses fork-aware transaction pool for better fork handling
|
|
- `--unsafe-force-node-key-generation` - Automatic P2P key generation
|
|
- `--unsafe-rpc-external` - RPC exposed externally (**development only!**)
|
|
- `--rpc-cors=all` - Allows all CORS origins
|
|
- `--force-authoring` - Forces block authoring even with a single validator (Alice only)
|
|
- `--no-prometheus` - Prometheus metrics disabled
|
|
- `--enable-offchain-indexing=true` - Enables offchain indexing
|
|
- `--discover-local` - Enables local peer discovery via mDNS
|
|
- `--alice` / `--bob` - Use well-known development identities
|
|
- `--provider` - Enables storage provider mode (MSP & BSP)
|
|
- `--provider-type=msp|bsp` - Type of storage provider
|
|
- `--max-storage-capacity` - Maximum storage capacity in bytes (1073741824 = 1 GiB)
|
|
- `--jump-capacity` - Jump capacity in bytes (104857600 = 100 MiB)
|
|
- `--msp-charging-period` - Charging period in blocks (MSP only)
|
|
|
|
### Node Types
|
|
The docker-compose setup includes five node types:
|
|
1. **Validators** (`NODE_TYPE=validator`) - Alice & Bob
|
|
- Run consensus and produce blocks
|
|
- Require 4 keys: gran, babe, imon, beef
|
|
2. **MSP** (`NODE_TYPE=msp`) - Charlie (name: msp)
|
|
- Main Storage Provider with storage provider capabilities
|
|
- Requires 1 key: bcsv
|
|
- Additional flags: `--provider`, `--provider-type=msp`, `--msp-charging-period`, storage capacity settings
|
|
3. **BSP** (`NODE_TYPE=bsp`) - Dave (bsp01) & Eve (bsp02)
|
|
- Backup Storage Provider with storage provider capabilities
|
|
- Requires 1 key: bcsv
|
|
- Additional flags: `--provider`, `--provider-type=bsp`, storage capacity settings
|
|
4. **Indexer** (no NODE_TYPE required) - StorageHub Indexer
|
|
- Full indexer node with database persistence
|
|
- No keys required (non-validating node)
|
|
- Additional flags: `--indexer`, `--indexer-mode=full`, `--indexer-database-url`
|
|
5. **Fisherman** (`NODE_TYPE=fisherman`) - Gustavo
|
|
- Monitors and validates storage provider behavior
|
|
- Requires 1 key: bcsv
|
|
- Additional flags: `--fisherman`, `--fisherman-database-url`
|
|
|
|
### Storage
|
|
- **Chain data**: Persisted in Docker volumes at `/data` (not using `--tmp`)
|
|
- **Keystore**: Persisted in Docker volumes at `/data/keystore` (`alice-keystore`, `bob-keystore`, `msp-keystore`, `bsp01-keystore`, `bsp02-keystore`, `fisherman-keystore`)
|
|
- **PostgreSQL data**: Persisted in `postgres-data` volume
|
|
- **Indexer data**: Persisted in `indexer-data` volume
|
|
- To clear all data and start fresh: `docker-compose down -v`
|
|
|
|
### User Permissions
|
|
- Containers run as `root` user to allow the entrypoint script to inject keys and set permissions
|
|
- The entrypoint script (`docker-entrypoint.sh`) switches to the `datahaven` user (UID 1001) before starting the node process
|
|
- Keystore and data directories are owned by `datahaven:datahaven`
|
|
|
|
### Security
|
|
All settings are configured for **local development only**:
|
|
- Uses well-known test seed phrase
|
|
- RPC exposed without authentication
|
|
- Unsafe flags enabled for convenience
|
|
|
|
## Troubleshooting
|
|
|
|
### Binary not found error
|
|
If you see "datahaven-node: No such file or directory", ensure:
|
|
1. You're in the operator directory: `cd operator`
|
|
2. You've built the binary: `cargo build --release`
|
|
3. You've copied it to the correct location: `cp target/release/datahaven-node build/`
|
|
Or simply run: `./prepare-docker.sh`
|
|
|
|
### Nodes not connecting
|
|
Check the logs to ensure nodes are peering correctly:
|
|
```bash
|
|
# Check if Bob connected to Alice
|
|
docker-compose logs bob | grep -i "peer\|sync"
|
|
|
|
# Check if MSP connected to Alice
|
|
docker-compose logs msp | grep -i "peer\|sync"
|
|
|
|
# View Alice's peer connections
|
|
docker-compose logs alice | grep -i "peer"
|
|
```
|
|
|
|
You should see messages like:
|
|
- `Discovered new external address`
|
|
- `Syncing` or `best: #X`
|
|
- Connection established messages
|
|
|
|
If nodes are not connecting:
|
|
1. Ensure Alice started first and is running: `docker-compose ps alice`
|
|
2. Verify Alice is accessible on the Docker network: `docker exec datahaven-bob ping alice`
|
|
3. Check Alice's peer ID matches the bootnode address in the config
|
|
|
|
### Port conflicts
|
|
If ports are already in use, modify the port mappings in `docker-compose.yml`:
|
|
```yaml
|
|
ports:
|
|
- "YOUR_PORT:9944" # Change YOUR_PORT to an available port
|
|
```
|
|
|
|
### Key injection issues
|
|
If you see key injection errors in the logs:
|
|
```bash
|
|
# Check the logs for key injection
|
|
docker-compose logs alice | grep "🔑"
|
|
|
|
# Verify keystore contents
|
|
docker exec datahaven-alice ls -la /keystore
|
|
```
|
|
|
|
To regenerate keys, remove the keystore volumes and restart:
|
|
```bash
|
|
docker-compose down -v
|
|
docker-compose up -d
|
|
```
|
|
|
|
### Checking node keys
|
|
To verify that keys were injected successfully:
|
|
```bash
|
|
# Alice keys (validator - 4 keys)
|
|
docker exec datahaven-alice ls -la /keystore
|
|
|
|
# Bob keys (validator - 4 keys)
|
|
docker exec datahaven-bob ls -la /keystore
|
|
|
|
# MSP keys (storage provider - 1 key)
|
|
docker exec datahaven-msp ls -la /data/keystore
|
|
|
|
# BSP keys (storage provider - 1 key)
|
|
docker exec datahaven-bsp01 ls -la /data/keystore
|
|
docker exec datahaven-bsp02 ls -la /data/keystore
|
|
|
|
# Fisherman keys (storage provider monitor - 1 key)
|
|
docker exec datahaven-fisherman ls -la /data/keystore
|
|
```
|
|
|
|
Validators should show: `babe`, `gran`, `imon`, and `beef`
|
|
Storage providers (MSP/BSP) and Fisherman should show: `bcsv`
|
|
|
|
### Checking Database Status
|
|
To verify the PostgreSQL database is working:
|
|
```bash
|
|
# Check PostgreSQL is running
|
|
docker exec datahaven-postgres pg_isready -U indexer -d datahaven
|
|
|
|
# Connect to database
|
|
docker exec -it datahaven-postgres psql -U indexer -d datahaven
|
|
|
|
# View indexer tables (once running)
|
|
docker exec datahaven-postgres psql -U indexer -d datahaven -c "\dt"
|
|
```
|
|
|