Docker
Tenzro Network provides official Docker images for running validator nodes, RPC nodes, and full network infrastructure. This guide covers building, configuring, and deploying Tenzro nodes using Docker and Docker Compose.
Official Docker Images
Docker images are built using multi-stage builds and can be hosted in your container registry. Images are typically built on CI/CD pipelines for version tracking.
Registry: Your container registry (GCR, ECR, ACR, Docker Hub)
Image: tenzro-node
Tags: latest, version tags, git commit SHA
Architecture: x86_64, aarch64 (multi-arch)
Dockerfile Configuration
The official Dockerfile uses multi-stage builds to produce minimal production images. The build process compiles the protocol modules and produces a single statically-linked binary.
# Multi-stage Dockerfile for tenzro-node
# Stage 1: Build environment
FROM rust:1.75-slim-bookworm AS builder
# Install build dependencies
RUN apt-get update && apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
cmake \
git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
# Copy workspace configuration
COPY Cargo.toml Cargo.lock rust-toolchain.toml ./
COPY crates/ crates/
# Build release binary with optimizations
RUN cargo build --release --bin tenzro-node
# Stage 2: Minimal runtime image
FROM debian:bookworm-slim
# Install runtime dependencies only
RUN apt-get update && apt-get install -y \
ca-certificates \
libssl3 \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user
RUN useradd -m -u 1000 tenzro
# Copy binary from builder
COPY --from=builder /build/target/release/tenzro-node /usr/local/bin/
# Set permissions
RUN chown tenzro:tenzro /usr/local/bin/tenzro-node
# Create data directory
RUN mkdir -p /data && chown tenzro:tenzro /data
USER tenzro
WORKDIR /data
# Expose ports
EXPOSE 9000 8545 8080 3001 3002
# Default command
ENTRYPOINT ["/usr/local/bin/tenzro-node"]
CMD ["--data-dir", "/data"]Build Arguments and Optimization
Production builds use Rust release optimizations with link-time optimization (LTO) and codegen-units=1 for maximum performance. Build time is approximately 15-20 minutes on modern hardware.
# Cargo.toml release profile [profile.release] opt-level = 3 lto = "fat" codegen-units = 1 strip = true panic = "abort"
Building Docker Images
Build the Docker image locally from the repository root. The build context includes all workspace crates.
# Build with default tag docker build -t tenzro-node:latest . # Build with specific tag and platform docker build -t tenzro-node:v0.1.0 --platform linux/amd64 . # Multi-architecture build (requires buildx) docker buildx build --platform linux/amd64,linux/arm64 \ -t tenzro-node:latest --push . # Build with cache mount for faster rebuilds docker build --cache-from tenzro-node:latest \ -t tenzro-node:dev .
Running Containers
Validator Node
Run a validator node with persistent data storage and exposed ports for P2P networking, JSON-RPC, and protocol servers.
# Run validator with volume mount docker run -d \ --name tenzro-validator \ --restart unless-stopped \ -p 9000:9000 \ -p 8545:8545 \ -p 8080:8080 \ -v tenzro-data:/data \ tenzro-node:latest \ --role validator \ --listen-addr /ip4/0.0.0.0/tcp/9000 \ --rpc-addr 0.0.0.0:8545 \ --data-dir /data # View logs docker logs -f tenzro-validator # Check node status docker exec tenzro-validator tenzro-node --help
RPC Node
RPC nodes serve JSON-RPC queries without participating in consensus. They require fewer resources than validators.
# Run RPC node docker run -d \ --name tenzro-rpc \ --restart unless-stopped \ -p 8545:8545 \ -p 8080:8080 \ -p 3001:3001 \ -p 3002:3002 \ -v tenzro-rpc-data:/data \ tenzro-node:latest \ --role light-client \ --rpc-addr 0.0.0.0:8545 \ --mcp-addr 0.0.0.0:3001 \ --a2a-addr 0.0.0.0:3002 \ --data-dir /data
Environment Variables
Configure node behavior using environment variables instead of CLI arguments. All configuration options support environment variable overrides.
# Environment variable reference TENZRO_ROLE=validator # Node role TENZRO_DATA_DIR=/data # Data directory TENZRO_LISTEN_ADDR=/ip4/0.0.0.0/tcp/9000 TENZRO_RPC_ADDR=0.0.0.0:8545 TENZRO_MCP_ADDR=0.0.0.0:3001 TENZRO_A2A_ADDR=0.0.0.0:3002 TENZRO_BOOT_NODES=/ip4/... # Bootstrap nodes TENZRO_CHAIN_ID=1337 # Chain ID RUST_LOG=info # Log level # Run with environment file docker run -d \ --name tenzro-node \ --env-file tenzro.env \ -v tenzro-data:/data \ tenzro-node:latest
Volume Persistence
Persistent storage is critical for validators and RPC nodes. The data directory contains RocksDB databases, snapshots, and keystore files.
Volume Structure
/data/ ├── rocksdb/ # RocksDB storage │ ├── blocks/ # CF_BLOCKS │ ├── state/ # CF_STATE │ ├── accounts/ # CF_ACCOUNTS │ ├── transactions/ # CF_TRANSACTIONS │ ├── metadata/ # CF_METADATA │ ├── snapshots/ # CF_SNAPSHOTS │ ├── settlements/ # CF_SETTLEMENTS │ ├── channels/ # CF_CHANNELS │ └── challenges/ # CF_CHALLENGES ├── snapshots/ # State snapshots ├── keystore/ # Encrypted keystores └── logs/ # Node logs
Named volumes provide portability and backup capabilities. Use bind mounts for direct host filesystem access.
# Create named volume docker volume create tenzro-data # Inspect volume docker volume inspect tenzro-data # Backup volume docker run --rm \ -v tenzro-data:/data \ -v $(pwd):/backup \ alpine tar czf /backup/tenzro-backup.tar.gz /data # Restore volume docker run --rm \ -v tenzro-data:/data \ -v $(pwd):/backup \ alpine tar xzf /backup/tenzro-backup.tar.gz -C / # Use bind mount (development only) docker run -d \ -v /host/path/data:/data \ tenzro-node:latest
Docker Compose
Docker Compose orchestrates multi-node deployments with networking, volumes, and service dependencies. This configuration runs a 3-validator network with 1 RPC node.
# docker-compose.yml
version: '3.8'
services:
validator-1:
image: tenzro-node:latest
container_name: tenzro-validator-1
restart: unless-stopped
ports:
- "9001:9000"
- "8546:8545"
volumes:
- validator-1-data:/data
environment:
TENZRO_ROLE: validator
TENZRO_DATA_DIR: /data
TENZRO_LISTEN_ADDR: /ip4/0.0.0.0/tcp/9000
RUST_LOG: info
networks:
- tenzro-net
validator-2:
image: tenzro-node:latest
container_name: tenzro-validator-2
restart: unless-stopped
ports:
- "9002:9000"
- "8547:8545"
volumes:
- validator-2-data:/data
environment:
TENZRO_ROLE: validator
TENZRO_DATA_DIR: /data
TENZRO_LISTEN_ADDR: /ip4/0.0.0.0/tcp/9000
RUST_LOG: info
networks:
- tenzro-net
depends_on:
- validator-1
validator-3:
image: tenzro-node:latest
container_name: tenzro-validator-3
restart: unless-stopped
ports:
- "9003:9000"
- "8548:8545"
volumes:
- validator-3-data:/data
environment:
TENZRO_ROLE: validator
TENZRO_DATA_DIR: /data
TENZRO_LISTEN_ADDR: /ip4/0.0.0.0/tcp/9000
RUST_LOG: info
networks:
- tenzro-net
depends_on:
- validator-1
- validator-2
rpc:
image: tenzro-node:latest
container_name: tenzro-rpc
restart: unless-stopped
ports:
- "8545:8545"
- "8080:8080"
- "3001:3001"
- "3002:3002"
volumes:
- rpc-data:/data
environment:
TENZRO_ROLE: light-client
TENZRO_DATA_DIR: /data
TENZRO_RPC_ADDR: 0.0.0.0:8545
TENZRO_MCP_ADDR: 0.0.0.0:3001
TENZRO_A2A_ADDR: 0.0.0.0:3002
RUST_LOG: info
networks:
- tenzro-net
depends_on:
- validator-1
- validator-2
- validator-3
networks:
tenzro-net:
driver: bridge
volumes:
validator-1-data:
validator-2-data:
validator-3-data:
rpc-data:Compose Commands
# Start all services docker-compose up -d # View logs for all services docker-compose logs -f # View logs for specific service docker-compose logs -f validator-1 # Stop all services docker-compose down # Stop and remove volumes (WARNING: data loss) docker-compose down -v # Restart specific service docker-compose restart rpc # Scale RPC nodes docker-compose up -d --scale rpc=3 # Check service status docker-compose ps
Health Checks
Docker health checks ensure nodes are running correctly. The health check queries the Web API health endpoint.
# Add to Dockerfile
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD curl -f http://localhost:8080/api/health || exit 1
# Or in docker-compose.yml
services:
validator-1:
image: tenzro-node:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"]
interval: 30s
timeout: 10s
start_period: 60s
retries: 3
# Check health status
docker inspect --format='{{json .State.Health}}' tenzro-validatorResource Limits
Set CPU and memory limits to prevent resource exhaustion. Validators require more resources than RPC nodes.
Validator Node:
CPU: 4 cores minimum (8 cores recommended)
Memory: 8 GB minimum (16 GB recommended)
Storage: 100 GB SSD minimum
RPC Node:
CPU: 2 cores minimum (4 cores recommended)
Memory: 4 GB minimum (8 GB recommended)
Storage: 50 GB SSD minimum
# Set resource limits
docker run -d \
--cpus="4" \
--memory="8g" \
--memory-swap="8g" \
--pids-limit=4096 \
tenzro-node:latest
# In docker-compose.yml
services:
validator-1:
image: tenzro-node:latest
deploy:
resources:
limits:
cpus: '4'
memory: 8G
reservations:
cpus: '2'
memory: 4GProduction Deployment
Production deployments use CI/CD pipelines for automated image builds with container registry storage. Images are tagged with git commit SHAs for version tracking.
# Example CI/CD pipeline configuration # Build and push Docker images with version tags docker build -t your-registry/tenzro-node:$GIT_SHA . docker build -t your-registry/tenzro-node:latest . docker push your-registry/tenzro-node:$GIT_SHA docker push your-registry/tenzro-node:latest # Deploy to Kubernetes kubectl set image deployment/tenzro-rpc \ tenzro-node=your-registry/tenzro-node:$GIT_SHA
Troubleshooting
Container Won't Start
# Check container logs docker logs tenzro-validator # Inspect container configuration docker inspect tenzro-validator # Check if ports are already bound netstat -tulpn | grep -E '9000|8545|8080' # Run with shell for debugging docker run -it --entrypoint /bin/sh tenzro-node:latest
Volume Permission Issues
# Check volume permissions docker run --rm -v tenzro-data:/data alpine ls -la /data # Fix ownership (Linux only) docker run --rm \ -v tenzro-data:/data \ alpine chown -R 1000:1000 /data
Network Connectivity
# Test RPC connectivity
curl http://localhost:8545 -X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
# Test health endpoint
curl http://localhost:8080/api/health
# Check container network
docker network inspect bridge