Changes:
- Add next-themes dependency for theme management
- Create ThemeProvider wrapper for app root layout
- Set dark mode as default theme
- Create ThemeToggle component with Sun/Moon icons
- Add theme toggle to home page navigation
- Add theme toggle to dashboard header
- App now starts in dark mode with ability to switch to light mode
Styling uses existing Tailwind dark mode variables configured in
tailwind.config.ts and globals.css. All existing components automatically
support dark theme.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
283 lines
7.6 KiB
YAML
283 lines
7.6 KiB
YAML
version: '3.8'
|
|
|
|
services:
|
|
# ================================================================
|
|
# MariaDB Database Service
|
|
# ================================================================
|
|
mariadb:
|
|
image: mariadb:latest
|
|
container_name: evoting_db
|
|
restart: unless-stopped
|
|
environment:
|
|
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-rootpass123}
|
|
MYSQL_DATABASE: ${DB_NAME:-evoting_db}
|
|
MYSQL_USER: ${DB_USER:-evoting_user}
|
|
MYSQL_PASSWORD: ${DB_PASSWORD:-evoting_pass123}
|
|
MYSQL_INITDB_SKIP_TZINFO: 1
|
|
ports:
|
|
- "${DB_PORT:-3306}:3306"
|
|
volumes:
|
|
- evoting_data:/var/lib/mysql
|
|
- ./docker/init.sql:/docker-entrypoint-initdb.d/01-init.sql
|
|
- ./docker/populate_past_elections.sql:/docker-entrypoint-initdb.d/02-populate.sql
|
|
- ./docker/create_active_election.sql:/docker-entrypoint-initdb.d/03-active.sql
|
|
networks:
|
|
- evoting_network
|
|
healthcheck:
|
|
test: ["CMD", "mariadb-admin", "ping", "-h", "localhost", "--silent"]
|
|
timeout: 20s
|
|
retries: 10
|
|
start_period: 40s
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ================================================================
|
|
# Bootnode Service (Peer Discovery for PoA Validators)
|
|
# ================================================================
|
|
bootnode:
|
|
build:
|
|
context: .
|
|
dockerfile: docker/Dockerfile.bootnode
|
|
container_name: evoting_bootnode
|
|
restart: unless-stopped
|
|
ports:
|
|
- "8546:8546"
|
|
networks:
|
|
- evoting_network
|
|
environment:
|
|
BOOTNODE_PORT: 8546
|
|
PYTHONUNBUFFERED: 1
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8546/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 10s
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ================================================================
|
|
# Backend FastAPI Service
|
|
# ================================================================
|
|
backend:
|
|
build:
|
|
context: .
|
|
dockerfile: docker/Dockerfile.backend
|
|
container_name: evoting_backend
|
|
restart: unless-stopped
|
|
environment:
|
|
DB_HOST: mariadb
|
|
DB_PORT: 3306
|
|
DB_NAME: ${DB_NAME:-evoting_db}
|
|
DB_USER: ${DB_USER:-evoting_user}
|
|
DB_PASSWORD: ${DB_PASSWORD:-evoting_pass123}
|
|
SECRET_KEY: ${SECRET_KEY:-your-secret-key-change-in-production}
|
|
DEBUG: ${DEBUG:-false}
|
|
PYTHONUNBUFFERED: 1
|
|
ports:
|
|
- "${BACKEND_PORT:-8000}:8000"
|
|
depends_on:
|
|
mariadb:
|
|
condition: service_healthy
|
|
volumes:
|
|
- ./backend:/app/backend
|
|
- backend_cache:/app/.cache
|
|
networks:
|
|
- evoting_network
|
|
command: uvicorn backend.main:app --host 0.0.0.0 --port 8000 --reload
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ================================================================
|
|
# PoA Validator 1 Service
|
|
# Proof-of-Authority blockchain consensus node
|
|
# ================================================================
|
|
validator-1:
|
|
build:
|
|
context: .
|
|
dockerfile: docker/Dockerfile.validator
|
|
container_name: evoting_validator_1
|
|
restart: unless-stopped
|
|
environment:
|
|
NODE_ID: validator-1
|
|
PRIVATE_KEY: ${VALIDATOR_1_PRIVATE_KEY:-0x1234567890abcdef}
|
|
BOOTNODE_URL: http://bootnode:8546
|
|
RPC_PORT: 8001
|
|
P2P_PORT: 30303
|
|
PYTHONUNBUFFERED: 1
|
|
ports:
|
|
- "8001:8001"
|
|
- "30303:30303"
|
|
depends_on:
|
|
- bootnode
|
|
networks:
|
|
- evoting_network
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8001/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 20s
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ================================================================
|
|
# PoA Validator 2 Service
|
|
# Proof-of-Authority blockchain consensus node
|
|
# ================================================================
|
|
validator-2:
|
|
build:
|
|
context: .
|
|
dockerfile: docker/Dockerfile.validator
|
|
container_name: evoting_validator_2
|
|
restart: unless-stopped
|
|
environment:
|
|
NODE_ID: validator-2
|
|
PRIVATE_KEY: ${VALIDATOR_2_PRIVATE_KEY:-0xfedcba9876543210}
|
|
BOOTNODE_URL: http://bootnode:8546
|
|
RPC_PORT: 8002
|
|
P2P_PORT: 30304
|
|
PYTHONUNBUFFERED: 1
|
|
ports:
|
|
- "8002:8002"
|
|
- "30304:30304"
|
|
depends_on:
|
|
- bootnode
|
|
networks:
|
|
- evoting_network
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8002/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 20s
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ================================================================
|
|
# PoA Validator 3 Service
|
|
# Proof-of-Authority blockchain consensus node
|
|
# ================================================================
|
|
validator-3:
|
|
build:
|
|
context: .
|
|
dockerfile: docker/Dockerfile.validator
|
|
container_name: evoting_validator_3
|
|
restart: unless-stopped
|
|
environment:
|
|
NODE_ID: validator-3
|
|
PRIVATE_KEY: ${VALIDATOR_3_PRIVATE_KEY:-0xabcdefabcdefabcd}
|
|
BOOTNODE_URL: http://bootnode:8546
|
|
RPC_PORT: 8003
|
|
P2P_PORT: 30305
|
|
PYTHONUNBUFFERED: 1
|
|
ports:
|
|
- "8003:8003"
|
|
- "30305:30305"
|
|
depends_on:
|
|
- bootnode
|
|
networks:
|
|
- evoting_network
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8003/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 20s
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ================================================================
|
|
# Frontend Next.js Service
|
|
# ================================================================
|
|
frontend:
|
|
build:
|
|
context: .
|
|
dockerfile: docker/Dockerfile.frontend
|
|
args:
|
|
NEXT_PUBLIC_API_URL: http://localhost:${BACKEND_PORT:-8000}
|
|
container_name: evoting_frontend
|
|
restart: unless-stopped
|
|
ports:
|
|
- "${FRONTEND_PORT:-3000}:3000"
|
|
depends_on:
|
|
- backend
|
|
- validator-1
|
|
- validator-2
|
|
- validator-3
|
|
environment:
|
|
NEXT_PUBLIC_API_URL: http://localhost:${BACKEND_PORT:-8000}
|
|
NODE_ENV: production
|
|
networks:
|
|
- evoting_network
|
|
healthcheck:
|
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ================================================================
|
|
# Optional: Adminer (Database Management UI)
|
|
# Access at http://localhost:8081
|
|
# ================================================================
|
|
adminer:
|
|
image: adminer:latest
|
|
container_name: evoting_adminer
|
|
restart: unless-stopped
|
|
ports:
|
|
- "8081:8080"
|
|
depends_on:
|
|
- mariadb
|
|
networks:
|
|
- evoting_network
|
|
environment:
|
|
ADMINER_DEFAULT_SERVER: mariadb
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
volumes:
|
|
evoting_data:
|
|
driver: local
|
|
backend_cache:
|
|
driver: local
|
|
|
|
networks:
|
|
evoting_network:
|
|
driver: bridge
|
|
ipam:
|
|
config:
|
|
- subnet: 172.25.0.0/16
|