Overview
Consensus provides Docker images for both production and demo deployments. The production image is optimized for security and performance, while the demo image includes automatic database resets for testing.
Production Deployment
Building the Image
The production Dockerfile uses a multi-stage build to create a minimal, secure container:
Build Production Image
Build with Custom Tag
docker build -t consensus:latest .
Image Architecture
The build process consists of two stages:
Build Stage
Uses node:22-alpine with build dependencies:
Python 3, make, and g++ for native modules (bcrypt, better-sqlite3)
Yarn 4 via corepack
Skips Puppeteer download to reduce image size
Compiles TypeScript to JavaScript
Production Stage
Creates a minimal runtime image:
Uses clean node:22-alpine base
Runs as non-root user nodejs (UID 1001)
Contains only production dependencies and compiled code
Exposes port 3000
Running the Container
Basic Usage
With Environment Variables
Custom Port and Data Directory
docker run -d \
--name consensus \
-p 3000:3000 \
-v consensus-data:/app/data \
consensus:latest
Always mount a volume to /app/data to persist your database. Without this, all election data will be lost when the container stops.
Docker Compose
Create a docker-compose.yml file for easier management:
version : '3.8'
services :
consensus :
image : consensus:latest
container_name : consensus
ports :
- "3000:3000"
volumes :
- consensus-data:/app/data
environment :
- NODE_ENV=production
- PORT=3000
- HOST=0.0.0.0
- SESSION_SECRET=${SESSION_SECRET}
- CONSENSUS_ADMIN_DEFAULT_PASSWORD=${CONSENSUS_ADMIN_DEFAULT_PASSWORD}
restart : unless-stopped
volumes :
consensus-data :
Create Environment File
Create a .env file with your secrets: SESSION_SECRET = your-very-secure-secret-key-change-this
CONSENSUS_ADMIN_DEFAULT_PASSWORD = admin-password-change-on-first-login
View Logs
docker-compose logs -f consensus
Demo Deployment
The demo deployment automatically resets the database at regular intervals, perfect for public demonstrations or testing.
Building the Demo Image
Build Production Image First
The demo image extends the production image: docker build -t consensus:latest .
Build Demo Image
docker build -f Dockerfile.demo -t consensus-demo:latest .
Running the Demo Container
Default (24-hour reset)
Custom Reset Interval
docker run -d \
--name consensus-demo \
-p 3000:3000 \
-e DEMO_MODE= true \
consensus-demo:latest
The demo container resets the database every 86400 seconds (24 hours) by default. It automatically kills the server process, deletes the database, runs the seed script, and restarts.
Demo Environment Variables
Variable Default Description DEMO_MODEtrueEnables demo mode DB_RESET_INTERVAL_SECONDS86400Database reset interval (24 hours) PORT3000Server port DATA_DIR/app/dataDatabase storage location
Container Management
View Logs
# Follow logs in real-time
docker logs -f consensus
# View last 100 lines
docker logs --tail 100 consensus
Access Container Shell
# Interactive shell
docker exec -it consensus sh
# Check database location
docker exec consensus ls -lh /app/data
Backup Database
# Copy database from container
docker cp consensus:/app/data/database.sqlite ./backup- $( date +%Y%m%d ) .sqlite
# Restore database to container
docker cp ./backup-20260101.sqlite consensus:/app/data/database.sqlite
docker restart consensus
Update Container
Pull/Build New Image
docker build -t consensus:latest .
Stop Old Container
docker stop consensus
docker rm consensus
Start New Container
docker run -d \
--name consensus \
-p 3000:3000 \
-v consensus-data:/app/data \
-e SESSION_SECRET="your-secret" \
consensus:latest
Security Considerations
Production Security Checklist:
Set a strong SESSION_SECRET (minimum 32 characters)
Change the default admin password on first login
Use HTTPS with a reverse proxy (nginx, Traefik)
Keep the Docker image updated
Restrict container network access
Regularly backup the database volume
Non-Root User
The container runs as user nodejs (UID 1001, GID 1001) for security. File permissions are set during the build process to ensure the application can read/write to /app/data.
Read-Only Root Filesystem
For additional security, you can run the container with a read-only root filesystem:
docker run -d \
--name consensus \
--read-only \
--tmpfs /tmp \
-v consensus-data:/app/data \
-p 3000:3000 \
consensus:latest
Troubleshooting
Container Won’t Start
# Check logs for errors
docker logs consensus
# Verify environment variables
docker inspect consensus | grep -A 20 Env
Permission Errors
If you see permission errors for /app/data:
# Check volume permissions
docker exec consensus ls -ld /app/data
# Should show: drwxr-xr-x nodejs nodejs
Database Locked
If you encounter “database is locked” errors:
# Ensure only one instance is running
docker ps | grep consensus
# Check for orphaned processes
docker exec consensus ps aux
Port Already in Use
# Find process using port 3000
lsof -i :3000
# Use a different port
docker run -d -p 8080:3000 consensus:latest
Next Steps
Configuration Learn about environment variables and configuration options
Security Implement security best practices for production