Initial public ModelForge release
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:17-alpine@sha256:18cfe3ef5e6815560c98237d6216d1e5119702fb0f3894c8785dd58b8bbe5d73
|
||||
environment:
|
||||
POSTGRES_DB: ${MODELFORGE_POSTGRES_DB:-modelforge}
|
||||
POSTGRES_USER: ${MODELFORGE_POSTGRES_ADMIN_USER:-postgres}
|
||||
POSTGRES_PASSWORD: ${MODELFORGE_POSTGRES_ADMIN_PASSWORD:?set a bootstrap-only PostgreSQL admin password}
|
||||
MODELFORGE_MIGRATION_DB_PASSWORD: ${MODELFORGE_MIGRATION_DB_PASSWORD:?set the non-superuser migration role password}
|
||||
MODELFORGE_RUNTIME_DB_PASSWORD: ${MODELFORGE_RUNTIME_DB_PASSWORD:?set the non-owner runtime role password}
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
- ./deploy/postgres/init:/docker-entrypoint-initdb.d:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${MODELFORGE_POSTGRES_ADMIN_USER:-postgres} -d ${MODELFORGE_POSTGRES_DB:-modelforge}"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 20
|
||||
ports:
|
||||
# Loopback only. The control-plane database holds provenance, credential hashes and the
|
||||
# audit trail; publishing it on every interface put all of that on the LAN behind a
|
||||
# development password. Override deliberately if a remote tool genuinely needs it.
|
||||
- "${MODELFORGE_POSTGRES_BIND:-127.0.0.1}:${MODELFORGE_POSTGRES_PORT:-5432}:5432"
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine@sha256:ff02b58f971e7d7d156a1267e283fcbbeee91773b6aa36c49dac28ecfe28eadf
|
||||
command: ["redis-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 20
|
||||
ports:
|
||||
# Loopback only. Redis has no authentication configured and holds transient request payloads.
|
||||
- "${MODELFORGE_REDIS_BIND:-127.0.0.1}:${MODELFORGE_REDIS_PORT:-6379}:6379"
|
||||
|
||||
api:
|
||||
build:
|
||||
context: ./backend
|
||||
args:
|
||||
# Build identity, so any image built from this file can say where it came from. An argument
|
||||
# that is never passed stays empty and is reported as null rather than guessed.
|
||||
MODELFORGE_VERSION: ${MODELFORGE_VERSION:-0.0.0}
|
||||
MODELFORGE_COMMIT: ${MODELFORGE_COMMIT:-}
|
||||
MODELFORGE_BUILT_AT: ${MODELFORGE_BUILT_AT:-}
|
||||
environment:
|
||||
MODELFORGE_DATABASE_URL: ${MODELFORGE_RUNTIME_DATABASE_URL:?set the modelforge_runtime SQLAlchemy URL}
|
||||
MODELFORGE_REDIS_URL: redis://redis:6379/0
|
||||
MODELFORGE_HF_HOME: /data/hf-cache
|
||||
MODELFORGE_ARTIFACT_ROOT: /data/artifacts
|
||||
MODELFORGE_QUARANTINE_ROOT: /data/quarantine
|
||||
MODELFORGE_CONFIG_ROOT: /app/config
|
||||
MODELFORGE_NODE_IDENTITY_FILE: /data/state/node-id
|
||||
MODELFORGE_NODE_IDENTITY_MODE: persisted
|
||||
MODELFORGE_HARDWARE_REFRESH_ON_STARTUP: "false"
|
||||
MODELFORGE_NODE_LIVENESS_MONITOR_ENABLED: "true"
|
||||
MODELFORGE_REGISTRY_SEED_ON_STARTUP: "true"
|
||||
MODELFORGE_OPERATOR_API_KEY: ${MODELFORGE_OPERATOR_API_KEY:-}
|
||||
MODELFORGE_HF_TOKEN: ${MODELFORGE_HF_TOKEN:-}
|
||||
MODELFORGE_NODE_STALE_AFTER_SECONDS: ${MODELFORGE_NODE_STALE_AFTER_SECONDS:-30}
|
||||
MODELFORGE_NODE_OFFLINE_AFTER_SECONDS: ${MODELFORGE_NODE_OFFLINE_AFTER_SECONDS:-90}
|
||||
MODELFORGE_LIVENESS_POLL_INTERVAL_SECONDS: ${MODELFORGE_LIVENESS_POLL_INTERVAL_SECONDS:-5}
|
||||
MODELFORGE_SERVING_RECONCILIATION_ENABLED: ${MODELFORGE_SERVING_RECONCILIATION_ENABLED:-true}
|
||||
MODELFORGE_LIFECYCLE_RECONCILIATION_ENABLED: ${MODELFORGE_LIFECYCLE_RECONCILIATION_ENABLED:-true}
|
||||
MODELFORGE_MIGRATION_RECONCILIATION_ENABLED: ${MODELFORGE_MIGRATION_RECONCILIATION_ENABLED:-true}
|
||||
MODELFORGE_OBSERVABILITY_MONITOR_ENABLED: ${MODELFORGE_OBSERVABILITY_MONITOR_ENABLED:-true}
|
||||
MODELFORGE_RECOVERY_RECONCILIATION_ENABLED: ${MODELFORGE_RECOVERY_RECONCILIATION_ENABLED:-true}
|
||||
MODELFORGE_SOURCE_COMMIT: ${MODELFORGE_SOURCE_COMMIT:-}
|
||||
MODELFORGE_SOURCE_REFERENCE: ${MODELFORGE_SOURCE_REFERENCE:-}
|
||||
MODELFORGE_SOURCE_REPOSITORY: ${MODELFORGE_SOURCE_REPOSITORY:-}
|
||||
MODELFORGE_BACKUP_ROOT: /data/backups
|
||||
MODELFORGE_BACKUP_RESTORE_ROOT: /data/restore
|
||||
MODELFORGE_BACKUP_ENCRYPTION_KEY: ${MODELFORGE_BACKUP_ENCRYPTION_KEY:-}
|
||||
MODELFORGE_BACKUP_ENCRYPTION_KEY_ID: ${MODELFORGE_BACKUP_ENCRYPTION_KEY_ID:-modelforge-backup-key-1}
|
||||
MODELFORGE_BACKUP_STALE_AFTER_SECONDS: ${MODELFORGE_BACKUP_STALE_AFTER_SECONDS:-93600}
|
||||
MODELFORGE_RESTORE_ALLOW_PRODUCTION_TARGET: ${MODELFORGE_RESTORE_ALLOW_PRODUCTION_TARGET:-false}
|
||||
MODELFORGE_OBSERVABILITY_POLL_INTERVAL_SECONDS: ${MODELFORGE_OBSERVABILITY_POLL_INTERVAL_SECONDS:-60}
|
||||
MODELFORGE_SERVING_RECONCILIATION_INTERVAL_SECONDS: ${MODELFORGE_SERVING_RECONCILIATION_INTERVAL_SECONDS:-5}
|
||||
MODELFORGE_SCHEDULER_SAFETY_RESERVE_BYTES: ${MODELFORGE_SCHEDULER_SAFETY_RESERVE_BYTES:-1073741824}
|
||||
volumes:
|
||||
- ./config:/app/config:ro
|
||||
- hf-cache:/data/hf-cache
|
||||
- model-artifacts:/data/artifacts
|
||||
- quarantine:/data/quarantine
|
||||
- modelforge-state:/data/state
|
||||
- ${MODELFORGE_BACKUP_VOLUME:-modelforge-backups}:/data/backups
|
||||
- ${MODELFORGE_RESTORE_VOLUME:-modelforge-restore}:/data/restore
|
||||
ports:
|
||||
- "${MODELFORGE_API_BIND:-0.0.0.0}:${MODELFORGE_API_PUBLISHED_PORT:-8000}:8000"
|
||||
cap_drop:
|
||||
- ALL
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
redis:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/v1/health/live')"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
|
||||
migrate:
|
||||
build:
|
||||
context: ./backend
|
||||
args:
|
||||
MODELFORGE_VERSION: ${MODELFORGE_VERSION:-0.0.0}
|
||||
MODELFORGE_COMMIT: ${MODELFORGE_COMMIT:-}
|
||||
MODELFORGE_BUILT_AT: ${MODELFORGE_BUILT_AT:-}
|
||||
command: ["alembic", "upgrade", "head"]
|
||||
environment:
|
||||
MODELFORGE_MIGRATION_DATABASE_URL: ${MODELFORGE_MIGRATION_DATABASE_URL:?set the non-superuser modelforge owner SQLAlchemy URL}
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
restart: "no"
|
||||
cap_drop:
|
||||
- ALL
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
|
||||
web:
|
||||
build:
|
||||
context: ./frontend
|
||||
args:
|
||||
VITE_API_BASE_URL: ${VITE_API_BASE_URL:-http://localhost:8000}
|
||||
MODELFORGE_VERSION: ${MODELFORGE_VERSION:-0.0.0}
|
||||
MODELFORGE_COMMIT: ${MODELFORGE_COMMIT:-}
|
||||
MODELFORGE_BUILT_AT: ${MODELFORGE_BUILT_AT:-}
|
||||
ports:
|
||||
- "${MODELFORGE_WEB_BIND:-127.0.0.1}:${MODELFORGE_WEB_PORT:-3000}:3000"
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp:size=16m,mode=1777
|
||||
cap_drop:
|
||||
- ALL
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
depends_on:
|
||||
api:
|
||||
condition: service_healthy
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
modelforge-backups:
|
||||
modelforge-restore:
|
||||
redis-data:
|
||||
hf-cache:
|
||||
model-artifacts:
|
||||
quarantine:
|
||||
modelforge-state:
|
||||
Reference in New Issue
Block a user