Docker Node Deployment
This guide covers deploying Monolythium nodes using Docker and docker-compose. Docker deployment is ideal for development, testing, and container-based infrastructure.
This guide covers Docker deployment. For host-native deployment with systemd, see Linux Host-Native Installation. Not sure which to choose? See Deployment Modes.
macOS does not support systemd. If you're running a node on macOS, you must use Docker mode for deployment and management.
Prerequisites
Required Software
- Docker: 20.10+ or later
- docker-compose: 2.0+ or later (V2 recommended)
- Operating System: Linux, macOS, or Windows with WSL2
Install Docker
Ubuntu/Debian:
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Add user to docker group (avoid sudo)
sudo usermod -aG docker $USER
newgrp docker
# Verify installation
docker --version
docker-compose --version
macOS:
# Install Docker Desktop
# Download from: https://www.docker.com/products/docker-desktop
# Verify installation
docker --version
docker-compose --version
Windows (WSL2):
# Install Docker Desktop for Windows
# Download from: https://www.docker.com/products/docker-desktop
# Ensure WSL2 integration is enabled in Docker Desktop settings
System Requirements
- CPU: 4+ cores
- RAM: 16GB+ (allocate at least 8GB to Docker)
- Storage: 500GB+ available for volumes
- Network: Ports 26656, 26657, 1317, 8545, 8546 available
Quickstart with Mono Commander
Mono Commander (monoctl) provides a streamlined Docker workflow.
Install Mono Commander
# Download binary
curl -LO https://github.com/monolythium/mono-commander/releases/latest/download/monoctl-linux-amd64
chmod +x monoctl-linux-amd64
sudo mv monoctl-linux-amd64 /usr/local/bin/monoctl
# Verify installation
monoctl --help
Initialize Docker Setup
# Initialize Docker configuration for Sprintnet
monoctl docker init --network Sprintnet
# This creates:
# - docker-compose.yml
# - .env file with network configuration
# - Volume directories for persistent data
Start Node
# Start node in background
monoctl docker up
# View logs
monoctl docker logs
# Follow logs in real-time
monoctl docker logs --follow
# Check status
monoctl docker status
Stop Node
# Stop node (preserves data)
monoctl docker down
# Stop and remove volumes (WARNING: deletes all data)
monoctl docker down -v
Restart Node
# Restart node container
monoctl docker restart
Upgrade Node
# Upgrade to a specific version
monoctl docker upgrade --version v1.2.3
# Upgrade to latest version
monoctl docker upgrade --version latest
Manual Docker Setup
If not using Mono Commander, you can create the configuration manually.
Directory Structure
# Create project directory
mkdir -p ~/monolythium-docker
cd ~/monolythium-docker
# Create volume directories
mkdir -p volumes/monod-data
mkdir -p volumes/monod-config
docker-compose.yml
Create a docker-compose.yml file:
version: "3.8"
services:
monod:
image: monolythium/monod:latest
container_name: monod
restart: unless-stopped
# Port mappings
ports:
- "26656:26656" # P2P
- "26657:26657" # RPC
- "1317:1317" # REST API
- "9090:9090" # gRPC
- "8545:8545" # EVM JSON-RPC
- "8546:8546" # EVM WebSocket
# Volume mappings
volumes:
- ./volumes/monod-data:/root/.monod
# Environment variables
environment:
- CHAIN_ID=mono-sprint-1
- MONIKER=my-docker-node
- MINIMUM_GAS_PRICES=1000000000alyth
# Resource limits
deploy:
resources:
limits:
cpus: '4.0'
memory: 16G
reservations:
cpus: '2.0'
memory: 8G
# Healthcheck
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:26657/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# Logging
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "3"
.env File
Create a .env file for environment-specific configuration:
# Network Configuration
CHAIN_ID=mono-sprint-1
NETWORK=Sprintnet
MONIKER=my-docker-node
# EVM Configuration
EVM_CHAIN_ID=262146
# Gas Configuration
MINIMUM_GAS_PRICES=1000000000alyth
# Node Configuration
PRUNING=default
PRUNING_KEEP_RECENT=100
PRUNING_INTERVAL=10
# API Configuration
API_ENABLE=true
GRPC_ENABLE=true
EVM_RPC_ENABLE=true
# Peer Configuration
PERSISTENT_PEERS=
SEEDS=
Start Docker Node
# Pull latest image
docker-compose pull
# Start in background
docker-compose up -d
# View logs
docker-compose logs -f monod
# Check status
docker-compose ps
Volume Configuration
Docker volumes persist data across container restarts and upgrades.
Default Volumes
| Volume Path (Host) | Container Path | Purpose |
|---|---|---|
./volumes/monod-data | /root/.monod | Chain data, config, keys |
Volume Backup
# Stop node
docker-compose down
# Backup volume
tar -czf monod-backup-$(date +%Y%m%d).tar.gz volumes/monod-data/
# Restore volume
tar -xzf monod-backup-20260104.tar.gz
# Start node
docker-compose up -d
Volume Permissions
# Fix ownership issues
sudo chown -R $(id -u):$(id -g) volumes/monod-data/
# Verify
ls -la volumes/monod-data/
Port Configuration
Default Ports
All ports are mapped 1:1 from container to host:
| Service | Container Port | Host Port | Protocol |
|---|---|---|---|
| P2P | 26656 | 26656 | TCP |
| RPC | 26657 | 26657 | TCP |
| REST API | 1317 | 1317 | TCP |
| gRPC | 9090 | 9090 | TCP |
| EVM JSON-RPC | 8545 | 8545 | TCP |
| EVM WebSocket | 8546 | 8546 | TCP |
Custom Port Mapping
To avoid conflicts, change host ports in docker-compose.yml:
ports:
- "36656:26656" # P2P on host port 36656
- "36657:26657" # RPC on host port 36657
- "31317:1317" # REST on host port 31317
- "38545:8545" # EVM RPC on host port 38545
Signing Model Explained
Keys in Container
In Docker deployments, validator signing keys are stored inside the container filesystem, backed by a volume.
Key files:
/root/.monod/config/priv_validator_key.json- Consensus signing key/root/.monod/config/node_key.json- P2P identity key/root/.monod/keyring-*/*- Account keys (if using keyring)
Accessing Keys
# View validator key (from host)
docker-compose exec monod cat /root/.monod/config/priv_validator_key.json
# Copy key to host
docker cp monod:/root/.monod/config/priv_validator_key.json ./priv_validator_key.json
# Import key to container
docker cp ./priv_validator_key.json monod:/root/.monod/config/priv_validator_key.json
docker-compose restart monod
Security Considerations
- Volume encryption: Consider encrypting the Docker volume at the host level
- Backup keys: Always maintain encrypted off-site backups
- HSM support: For production validators, use remote signing with Tendermint KMS
- Access control: Restrict Docker daemon access to trusted users only
For production validators with high stake, consider using Tendermint KMS with hardware security modules (HSM) instead of storing keys directly in containers.
Upgrade Procedure
Pull New Image
# Check for new image
docker pull monolythium/monod:latest
# View image history
docker images monolythium/monod
Upgrade Node
# Stop current node
docker-compose down
# Pull new image
docker-compose pull
# Start with new image
docker-compose up -d
# Verify upgrade
docker-compose exec monod monod version
docker-compose logs -f monod
Rollback
# Stop node
docker-compose down
# Specify previous version in docker-compose.yml
# Change: image: monolythium/monod:latest
# To: image: monolythium/monod:v0.1.0
# Start with old image
docker-compose up -d
Zero-Downtime Upgrade (Advanced)
For RPC nodes, you can use blue-green deployment:
# Start new node on different ports
docker-compose -f docker-compose-v2.yml up -d
# Wait for sync
# Switch traffic (load balancer, DNS, etc.)
# Stop old node
docker-compose down
Monitoring and Logs
View Logs
# View all logs
docker-compose logs monod
# Follow logs in real-time
docker-compose logs -f monod
# Last 100 lines
docker-compose logs --tail=100 monod
# Logs since 1 hour ago
docker-compose logs --since=1h monod
Container Stats
# Real-time resource usage
docker stats monod
# Container inspection
docker inspect monod
# View processes inside container
docker-compose exec monod ps aux
Health Checks
# Check container health
docker-compose ps
# Manual health check
curl http://localhost:26657/health
# RPC status
curl http://localhost:26657/status
# EVM RPC check
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \
http://localhost:8545
Troubleshooting
Container Fails to Start
Symptom: Container exits immediately after start
Solution:
# Check logs
docker-compose logs monod
# Common issues:
# 1. Port conflict - change port mappings
# 2. Volume permissions - fix ownership
# 3. Invalid genesis - re-download genesis file
# Run container interactively for debugging
docker-compose run --rm monod /bin/bash
Volume Permission Denied
Symptom: permission denied errors in logs
Solution:
# Fix volume ownership
sudo chown -R $(id -u):$(id -g) volumes/monod-data/
# Verify
ls -la volumes/monod-data/
# Restart container
docker-compose restart monod
Container Not Accessible
Symptom: Cannot connect to RPC endpoints from host
Solution:
# Check container is running
docker-compose ps
# Check port bindings
docker port monod
# Test from inside container
docker-compose exec monod curl localhost:26657/health
# Check firewall rules on host
sudo iptables -L -n
# Check Docker network
docker network inspect monolythium-docker_default
Out of Disk Space
Symptom: Container stops, disk full errors
Solution:
# Check disk usage
df -h
# Check Docker disk usage
docker system df
# Prune unused Docker resources
docker system prune -a
# Check volume size
du -sh volumes/monod-data/
# Increase host disk or prune old data
Container Restart Loop
Symptom: Container constantly restarting
Solution:
# Check restart count
docker-compose ps
# View logs for crash reason
docker-compose logs --tail=200 monod
# Disable restart to debug
# In docker-compose.yml, change:
# restart: unless-stopped
# To: restart: "no"
# Start and investigate
docker-compose up monod
Slow Sync Performance
Symptom: Node syncing very slowly
Solution:
# Check peer count
docker-compose exec monod curl -s localhost:26657/net_info | jq '.result.n_peers'
# Check resource limits
docker stats monod
# Increase CPU/memory in docker-compose.yml
# Verify disk I/O is not bottleneck (use SSD)
# Consider using state-sync instead
# See: https://docs.monolythium.com/operators/state-sync
Cannot Execute Binary in Container
Symptom: exec format error or not found
Solution:
# Check image architecture matches host
docker inspect monolythium/monod:latest | jq '.[0].Architecture'
# Verify platform
uname -m
# Pull correct architecture
docker pull --platform linux/amd64 monolythium/monod:latest
# or
docker pull --platform linux/arm64 monolythium/monod:latest
Advanced Configuration
Multi-Node Setup
Run multiple nodes on the same host:
# Create separate directories
mkdir -p node1 node2
# Copy and modify docker-compose.yml for each
cd node1
# Change container name, ports, volumes
cd ../node2
# Change container name, ports, volumes
# Start both
docker-compose -f node1/docker-compose.yml up -d
docker-compose -f node2/docker-compose.yml up -d
Custom Entrypoint
Override the default entrypoint for debugging:
# In docker-compose.yml
entrypoint: ["/bin/bash", "-c"]
command:
- |
monod init my-node --chain-id mono-sprint-1 || true
monod start --home /root/.monod
Resource Limits
Fine-tune resource allocation:
deploy:
resources:
limits:
cpus: '8.0'
memory: 32G
pids: 4096
reservations:
cpus: '4.0'
memory: 16G
Next Steps
After successful Docker deployment:
- Deployment Modes - Understand Docker vs host-native
- Mono Commander - Operator tool (works with Docker)
- Join Network - Connect to a network
- State Sync - Fast sync for new nodes
- Monitoring - Set up observability