Skip to main content
Version: 1.0.1

Quick Start

Get Milvaion running locally and execute your first job in under 10 minutes.

Prerequisites

You need:

  • Docker Desktop (v20.10+) with Docker Compose
  • Web browser for the dashboard and built-in Open Api Rest Client
  • (Optional )curl or a REST client (Postman, Insomnia)

Verify Docker is installed:

docker --version
# Docker version 24.0.0 or higher

docker compose version
# Docker Compose version v2.20.0 or higher

Step 1: Start the Stack

Create a file named docker-compose.yml:

services:
# PostgreSQL Database
postgres:
image: postgres:16-alpine
container_name: milvaion-postgres
environment:
POSTGRES_DB: MilvaionDb
POSTGRES_USER: postgres
POSTGRES_PASSWORD: N4SQp.qW>6?xwWzg
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- milvaion-network
restart: unless-stopped
mem_limit: 8096m
mem_reservation: 2048m
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d MilvaionDb"]
interval: 5s
timeout: 5s
retries: 10
start_period: 30s

# Redis Cache & Scheduler
redis:
image: redis:7-alpine
container_name: milvaion-redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- milvaion-network
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5

# RabbitMQ Message Broker
rabbitmq:
image: rabbitmq:3-management-alpine
container_name: milvaion-rabbitmq
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
ports:
- "5672:5672" # AMQP port
- "15672:15672" # Management UI
volumes:
- rabbitmq_data:/var/lib/rabbitmq
networks:
- milvaion-network
restart: unless-stopped
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "ping"]
interval: 10s
timeout: 5s
retries: 5

# Seq log server
seq:
image: datalust/seq:latest
container_name: milvaion-seq
environment:
- SEQ_FIRSTRUN_ADMINPASSWORD=ChangeMe123!
- ACCEPT_EULA=Y
ports:
- "5341:80" # Seq default UI port mapped to host 5341
volumes:
- seq_data:/data
networks:
- milvaion-network
restart: unless-stopped
labels:
- "com.milvaion.service=seq"
- "com.milvaion.description=Seq logging server"

# Milvaion API (Producer/Scheduler)
milvaion-api:
image: milvasoft/milvaion-api:latest
container_name: milvaion-api
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://+:5000
- Cors__Policies__AllowAll__AllowCredentials=false
- MILVAION_ROOT_PASSWORD=admin
- MILVA_ENV=dev
ports:
- "5000:5000" # API + React SPA (http://localhost:5000)
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
networks:
- milvaion-network
restart: unless-stopped
mem_limit: 2048m
labels:
- "com.milvaion.service=api"
- "com.milvaion.description=Milvaion API with embedded React UI"

# SampleWorker (Job Executor) - Scalable
sample-worker:
image: milvasoft/milvaion-sampleworker:latest
environment:
- Worker__WorkerId=sample-worker
depends_on:
rabbitmq:
condition: service_healthy
redis:
condition: service_healthy
milvaion-api:
condition: service_started
networks:
- milvaion-network
restart: unless-stopped
mem_limit: 1024m
# Enable scaling: docker-compose up --scale sample-worker=4 -d
deploy:
replicas: 1

volumes:
postgres_data:
driver: local
redis_data:
driver: local
rabbitmq_data:
driver: local
seq_data:
driver: local

networks:
milvaion-network:
driver: bridge

Start all services:

docker compose up -d

Wait 30-60 seconds for all services to initialize, then verify:

docker compose ps

You should see all containers running:

NAME                  STATUS          PORTS
milvaion-api Up 0.0.0.0:5000->8080/tcp
milvaion-postgres Up (healthy) 0.0.0.0:5432->5432/tcp
milvaion-rabbitmq Up (healthy) 5672/tcp, 0.0.0.0:15672->15672/tcp
milvaion-redis Up (healthy) 0.0.0.0:6379->6379/tcp
milvaion-sample-worker Up

Step 2: Access the Dashboard and Rest Client

Dashboard

Open your browser: http://localhost:5000

You'll see the Milvaion UI. For more information, see the detailed UI documentation.

Milvaion Dashboard

Default username is rootuser. System-wide access is permitted. If you didn't set MILVAION_ROOT_PASSWORD in docker-compose, to get the initial user password:

docker logs milvaion-api 2>&1 | grep -i "password"

Rest Client

Open your browser: http://localhost:5000/api/documentation/index.html

You'll see the Milvaion rest client. A permanent token will be set up for you. Milvaion Dashboard

Without proxy, the api will serve only http. For http/https switch on rest client; Milvaion Dashboard

Step 3: Create Your First Job

Use the Dashboard UI, Rest Client or make an API call:

curl -X POST http://localhost:5000/api/v1/jobs/job \
-H "Content-Type: application/json" \
-H "Accept-Language: en-US" \
-d '{
"displayName": "My First Job",
"description": "This is a test job!",
"tags": "test,first-job",
"workerId": "sample-worker-01",
"selectedJobName": "SampleJob",
"cronExpression": "* * * * *",
"executeAt": null,
"isActive": true,
"concurrentExecutionPolicy": 0,
"timeoutMinutes": null,
"jobData": "{\"message\": \"Hello from Milvaion!\"}"
}'

What this does:

FieldValueMeaning
displayName"My First Job"Human-readable name shown in dashboard
description"This is a test job!"Human-readable description shown in dashboard
tags"test,first-job"Comma seperated tags for job grouping.
workerId"sample-worker-01"Routes to the test worker. This must be exactly the same as your worker configuration.
selectedJobName"SampleJob"Job class name in worker. Must match a job class in the worker
cronExpression* * * * *Schedule configuration. Run every minute
executeAt"2026-01-15T15:39:00.000Z"One time job schedule time. Send null for the recurring jobs. If both cronExpression and executeAt sent, cronExpression have priority.
concurrentExecutionPolicy0 -> Skip , 1 -> QueueScheduling mechanism when concurrent execution happens.
isActivetrueJob is active or not. Deactivated jobs will not create executions.
timeoutMinutesnullJob timeout in minutes. Default is 10 minute.
jobDataJSON objectData passed to the job

You should receive:

{
"isSuccess": true,
"statusCode": 200,
"messages": [
{
"key": "",
"message": "Operation successful!",
"type": 1
}
],
"data": "019bbd29-3321-7a70-9015-489f703db53f",
"metadatas": []
}

The data field is your new Job ID.

Step 4: Watch It Run

  1. Go to http://localhost:5000
  2. Login with your credentials.
  3. Click Jobs in the sidebar
  4. Click your job name
  5. Wait up to 1 minute for the cron trigger
  6. See the Execution History populate with occurrences in real-time
  7. Click an occurrence to see real-time logs

Option B: Worker Logs

docker logs -f milvaion-sample-worker

Expected output when job runs:

info: SampleJob[0]
🚀 SampleJob started!
info: SampleJob[0]
Job ID: f47ac10b-58cc-4372-a567-0e02b2c3d479
info: SampleJob[0]
Received data: {"message":"Hello from Milvaion!"}
info: SampleJob[0]
⏳ Processing step 1/5...
info: SampleJob[0]
⏳ Processing step 2/5...
...
info: SampleJob[0]
✅ SampleJob completed successfully!

Step 5: Trigger Manually (Optional)

Don't want to wait for cron → Trigger immediately via Dashboard or:

curl -X POST "http://localhost:5000/api/v1/jobs/job/trigger" \
-H "Content-Type: application/json" \
-d '{
"jobId": "YOUR_JOB_ID",
"reason": "Manual test"
"force": true
}'

Verify the System

API Health

curl http://localhost:5000/api/v1/healthcheck

List Workers

curl http://localhost:5000/api/v1/workers

List Job Occurrences(Executions)

curl "http://localhost:5000/api/v1/jobs/occurrences"

RabbitMQ Management

Open http://localhost:15672 (guest/guest) to see queues and message flow.

Cleanup

Stop all services:

docker compose down

Stop and delete all data (fresh start):

docker compose down -v

Troubleshooting

"Job not executing"

  1. Check worker is running: docker compose ps
  2. Check worker logs: docker logs milvaion-sample-worker
  3. Verify job is active in dashboard
  4. Check RabbitMQ has queues: http://localhost:15672 → Queues

"API won't start"

  1. Check PostgreSQL is healthy: docker logs milvaion-postgres
  2. Wait for migrations: docker logs milvaion-api | grep -i migration
  3. Port conflict → Change 5000:8080 to 5001:8080

"Worker can't connect"

  1. Ensure worker is on same Docker network
  2. Use container names (rabbitmq, redis) in connection strings, not localhost
  3. Check RabbitMQ is healthy: docker logs milvaion-rabbitmq

What's Next?

Now that Milvaion is running:

  1. Core Concepts - Understand the architecture
  2. Your First Worker - Create a custom worker with your own jobs
  3. Configuration Reference - All available settings