Skip to main content

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.

Deployment Mode

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 Users

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 PathPurpose
./volumes/monod-data/root/.monodChain 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:

ServiceContainer PortHost PortProtocol
P2P2665626656TCP
RPC2665726657TCP
REST API13171317TCP
gRPC90909090TCP
EVM JSON-RPC85458545TCP
EVM WebSocket85468546TCP

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
Production Validators

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: