Stacks
stack.toml composes multiple services into a single deployable unit — the niso equivalent of docker-compose.yml.
Basic stack#
A stack file defines multiple services, their dependencies, and shared resources:
stack.toml
1[stack]2name = "my-platform"34[networks]5backend = { subnet = "10.99.1.0/24" }6frontend = { subnet = "10.99.2.0/24" }78[[service]]9name = "api"10package = "my-api:1.0.0"11ports = ["8080:8080"]12networks = ["backend", "frontend"]13depends_on = { db = "healthy", cache = "started" }1415[service.environment]16DATABASE_URL = "postgres://app:secret@db.niso.local:5432/mydb"17REDIS_URL = "redis://cache.niso.local:6379"1819[[service]]20name = "db"21package = "postgres:16"22networks = ["backend"]23volumes = { pgdata = { mount = "/data", exclusive = true } }2425[service.environment]26POSTGRES_PASSWORD = "secret"2728[[service]]29name = "cache"30package = "redis:7"31networks = ["backend"]3233[[service]]34name = "migrate"35package = "my-api:1.0.0"36type = "oneshot"37networks = ["backend"]38depends_on = { db = "healthy" }3940[service.binary]41entrypoint = "my-api"42args = ["migrate"]Stack commands#
bash
# Validate stack file$ niso stack validate# Deploy all services (respects dependency order)$ niso stack up ✓ Network backend created (10.99.1.0/24) ✓ Network frontend created (10.99.2.0/24) ✓ db started (healthy in 3s) ✓ cache started ✓ migrate completed (exit 0) ✓ api started (healthy in 2s)# Show stack status$ niso stack status SERVICE STATUS HEALTH UPTIME api active healthy 5m db active healthy 5m cache active running 5m# Show what would change$ niso stack diff# Upgrade a single service$ niso stack upgrade api 1.1.0# Restart a service$ niso stack restart api# View logs across all services$ niso stack logs -f# View logs for one service$ niso stack logs api -f# Wait for a service to become healthy$ niso stack wait api# Tear down$ niso stack down# Tear down including volumes$ niso stack down --volumesDependency conditions#
Control service startup order with three dependency conditions:
started— the dependency process is runninghealthy— the dependency's health check is passingcompleted— the dependency (oneshot) finished with exit 0
toml
[[service]]name = "api"depends_on = { db = "healthy", # Wait for db health check migrate = "completed", # Wait for migration to finish cache = "started", # Just needs to be running}Service types#
Two service types:
service(default) — long-running process, restarted on failureoneshot— runs once and exits (migrations, seed data, setup scripts)
Profiles#
Use profiles to define optional services that are only started when requested:
toml
[[service]]name = "debug-tools"package = "debug-toolkit:1.0.0"profiles = ["debug"][[service]]name = "prometheus"package = "prometheus:2.50"profiles = ["monitoring"]bash
# Start with monitoring profile$ niso stack up --profile monitoring# Start with multiple profiles$ niso stack up --profile monitoring --profile debugService inheritance#
Use extends to share configuration between services:
toml
[[service]]name = "base-worker"package = "my-app:1.0.0"networks = ["backend"][service.isolation.resources]memory_max = "256M"[[service]]name = "email-worker"extends = "base-worker"[service.environment]QUEUE = "email"[[service]]name = "report-worker"extends = "base-worker"[service.environment]QUEUE = "reports"[service.isolation.resources]memory_max = "512M" # Override baseSecrets#
Reference secret files in the stack. They are mounted read-only into the service:
toml
[secrets]db_password = { file = "./secrets/db_password.txt" }api_key = { file = "./secrets/api_key.txt" }[[service]]name = "api"secrets = ["db_password", "api_key"]Watch mode#
During development, watch for changes and automatically redeploy:
bash
$ niso stack watch Watching for changes... [api] manifest.toml changed → redeploying ✓ api restarted