feat(docker): single-container staking node for GUI integration
Dockerfile.staking-node — runs daemon + wallet with PoS staking in one
container using supervisord. No docker-compose needed.
For the CoreGUI desktop app to run on Windows/Mac/Linux:
docker run -d -p 46941:36941 -p 46942:36942 -p 46944:36944 \
-v lthn-chain:/data -v lthn-wallet:/wallet \
-e WALLET_PASSWORD=pass \
lthn/staking-node
Built-in helpers:
docker exec <name> /status.sh — chain + wallet status
docker exec <name> /wallet-address.sh — get wallet address
Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
parent
e1292a6445
commit
3fd1af9824
1 changed files with 182 additions and 0 deletions
182
docker/Dockerfile.staking-node
Normal file
182
docker/Dockerfile.staking-node
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
# Lethean Staking Node — single container, no compose needed
|
||||
# Runs daemon + wallet with PoS staking in one container.
|
||||
#
|
||||
# Build:
|
||||
# docker build -f Dockerfile.staking-node -t lthn/staking-node .
|
||||
#
|
||||
# Run:
|
||||
# docker run -d --name lthn-staker \
|
||||
# -p 46941:36941 -p 46942:36942 -p 46944:36944 \
|
||||
# -v lthn-chain:/data -v lthn-wallet:/wallet \
|
||||
# lthn/staking-node
|
||||
#
|
||||
# Run with password:
|
||||
# docker run -d --name lthn-staker \
|
||||
# -e WALLET_PASSWORD=my-pass \
|
||||
# -p 46941:36941 -p 46942:36942 -p 46944:36944 \
|
||||
# -v lthn-chain:/data -v lthn-wallet:/wallet \
|
||||
# lthn/staking-node
|
||||
#
|
||||
# Check status:
|
||||
# docker exec lthn-staker /status.sh
|
||||
#
|
||||
# Get wallet address:
|
||||
# docker exec lthn-staker /wallet-address.sh
|
||||
#
|
||||
# Ports:
|
||||
# 36941 — Daemon RPC (chain queries)
|
||||
# 36942 — P2P (open on router for full node)
|
||||
# 36944 — Wallet RPC (balance, transfers)
|
||||
|
||||
FROM lthn/chain:testnet
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl supervisor bc \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Supervisor manages both daemon and wallet in one container
|
||||
COPY <<'SUPERVISOR' /etc/supervisor/conf.d/lethean.conf
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/dev/stdout
|
||||
logfile_maxbytes=0
|
||||
loglevel=info
|
||||
|
||||
[program:daemon]
|
||||
command=lethean-chain-node
|
||||
--data-dir /data
|
||||
--rpc-bind-ip 0.0.0.0
|
||||
--rpc-bind-port 36941
|
||||
--p2p-bind-port 36942
|
||||
--rpc-enable-admin-api
|
||||
--allow-local-ip
|
||||
--log-level %(ENV_DAEMON_LOG_LEVEL)s
|
||||
--disable-upnp
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:wallet]
|
||||
command=/start-wallet.sh
|
||||
autorestart=true
|
||||
startsecs=30
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
SUPERVISOR
|
||||
|
||||
# Wallet startup script — waits for daemon, creates wallet if needed
|
||||
COPY <<'WALLETSH' /start-wallet.sh
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
WALLET_FILE="/wallet/staker.wallet"
|
||||
WALLET_PASS="${WALLET_PASSWORD:-}"
|
||||
DAEMON="127.0.0.1:36941"
|
||||
|
||||
# Wait for daemon RPC
|
||||
echo "[wallet] Waiting for daemon..."
|
||||
until curl -sf "http://$DAEMON/json_rpc" \
|
||||
-d '{"jsonrpc":"2.0","id":"0","method":"getinfo"}' \
|
||||
-H 'Content-Type: application/json' > /dev/null 2>&1; do
|
||||
sleep 5
|
||||
done
|
||||
echo "[wallet] Daemon ready"
|
||||
|
||||
# Create wallet if it doesn't exist
|
||||
if [ ! -f "$WALLET_FILE" ]; then
|
||||
echo "[wallet] Creating new wallet..."
|
||||
echo "$WALLET_PASS" | lethean-wallet-cli \
|
||||
--generate-new-wallet "$WALLET_FILE" \
|
||||
--password "$WALLET_PASS" \
|
||||
--daemon-address "$DAEMON" \
|
||||
--command exit
|
||||
echo "[wallet] Wallet created"
|
||||
fi
|
||||
|
||||
# Start wallet with PoS staking
|
||||
exec lethean-wallet-cli \
|
||||
--wallet-file "$WALLET_FILE" \
|
||||
--password "$WALLET_PASS" \
|
||||
--daemon-address "$DAEMON" \
|
||||
--rpc-bind-port 36944 \
|
||||
--rpc-bind-ip 0.0.0.0 \
|
||||
--do-pos-mining
|
||||
WALLETSH
|
||||
|
||||
# Status helper — shows chain + wallet in one command
|
||||
COPY <<'STATUSSH' /status.sh
|
||||
#!/bin/bash
|
||||
echo "=== Lethean Staking Node ==="
|
||||
echo ""
|
||||
|
||||
# Chain
|
||||
INFO=$(curl -sf http://127.0.0.1:36941/json_rpc \
|
||||
-d '{"jsonrpc":"2.0","id":"0","method":"getinfo"}' \
|
||||
-H 'Content-Type: application/json' 2>/dev/null)
|
||||
|
||||
if [ -n "$INFO" ]; then
|
||||
echo "$INFO" | python3 -c "
|
||||
import sys,json
|
||||
d=json.load(sys.stdin)['result']
|
||||
hf=d.get('is_hardfok_active',[])
|
||||
active=sum(1 for h in hf if h)
|
||||
print(f'Chain:')
|
||||
print(f' Height: {d[\"height\"]:,}')
|
||||
print(f' Hardforks: HF0-{active-1}')
|
||||
print(f' PoW diff: {d.get(\"pow_difficulty\",0):,}')
|
||||
print(f' Aliases: {d.get(\"alias_count\",0)}')
|
||||
print(f' Peers in: {d.get(\"incoming_connections_count\",0)}')
|
||||
print(f' Peers out: {d.get(\"outgoing_connections_count\",0)}')
|
||||
print(f' Status: {d[\"status\"]}')
|
||||
" 2>/dev/null
|
||||
else
|
||||
echo "Chain: starting..."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Wallet
|
||||
BAL=$(curl -sf http://127.0.0.1:36944/json_rpc \
|
||||
-d '{"jsonrpc":"2.0","id":"0","method":"getbalance"}' \
|
||||
-H 'Content-Type: application/json' 2>/dev/null)
|
||||
|
||||
if [ -n "$BAL" ]; then
|
||||
echo "$BAL" | python3 -c "
|
||||
import sys,json
|
||||
d=json.load(sys.stdin)['result']
|
||||
print(f'Wallet:')
|
||||
print(f' Balance: {d[\"balance\"]/1e12:.4f} LTHN')
|
||||
print(f' Unlocked: {d[\"unlocked_balance\"]/1e12:.4f} LTHN')
|
||||
print(f' Staking: yes (PoS mining active)')
|
||||
" 2>/dev/null
|
||||
else
|
||||
echo "Wallet: syncing..."
|
||||
fi
|
||||
STATUSSH
|
||||
|
||||
# Wallet address helper
|
||||
COPY <<'ADDRSH' /wallet-address.sh
|
||||
#!/bin/bash
|
||||
curl -sf http://127.0.0.1:36944/json_rpc \
|
||||
-d '{"jsonrpc":"2.0","id":"0","method":"getaddress"}' \
|
||||
-H 'Content-Type: application/json' | python3 -c "
|
||||
import sys,json
|
||||
d=json.load(sys.stdin)['result']
|
||||
print(d['address'])
|
||||
" 2>/dev/null || echo "Wallet not ready yet — daemon still syncing"
|
||||
ADDRSH
|
||||
|
||||
RUN chmod +x /start-wallet.sh /status.sh /wallet-address.sh
|
||||
|
||||
ENV DAEMON_LOG_LEVEL=1
|
||||
ENV WALLET_PASSWORD=
|
||||
|
||||
EXPOSE 36941 36942 36944
|
||||
|
||||
VOLUME ["/data", "/wallet"]
|
||||
|
||||
ENTRYPOINT ["supervisord", "-c", "/etc/supervisor/conf.d/lethean.conf"]
|
||||
Loading…
Add table
Reference in a new issue