Skip to main content

Running with Docker

Vectra ships pre-built Dockerfiles for three targets, located in the .docker/ directory:

FileBase OSRuntime
Dockerfile.linuxLinux (glibc)linux-x64
Dockerfile.windows-ltsc2022Windows Nano Server LTSC 2022win-x64
Dockerfile.windows-ltsc2025Windows Nano Server LTSC 2025win-x64

All images:

  • Expose port 7080 (HTTP) by default
  • Set DOTNET_RUNNING_IN_CONTAINER=true
  • Accept an APP_VERSION build argument

Building the Image

Run all commands from the repository root so the build context includes the full src/ tree.

docker build \
-f .docker/Dockerfile.linux \
--build-arg APP_VERSION=1.0.0 \
-t vectra:1.0.0 \
.

Running the Container

Minimal (in-memory cache, SQLite)

docker run -d \
--name vectra \
-p 7080:7080 \
-e System__Storage__Database__Providers__Sqlite__ConnectionString="Data Source=/data/vectra.db" \
-e Policy__Providers__Internal__Directory="/policies" \
-v $(pwd)/data:/data \
-v $(pwd)/policies:/policies \
vectra:1.0.0
tip

ASP.NET Core reads configuration from environment variables using double-underscore __ as a section separator. System__Server__Http__Port=7080 maps to System → Server → Http → Port.


Environment Variables Reference

All appsettings.json keys can be overridden via environment variables using __ as a delimiter.

Environment VariableExample ValueDescription
System__Server__Http__Port7080HTTP listener port
System__Server__Https__EnabledtrueEnable HTTPS
System__Server__Https__Port7443HTTPS listener port
System__Storage__Database__DefaultProviderSqliteDatabase provider
System__Storage__Database__Providers__Sqlite__ConnectionStringData Source=/data/vectra.dbSQLite path
System__Storage__Database__Providers__Postgres__ConnectionStringHost=db;Database=vectra;...PostgreSQL connection
System__Storage__Cache__DefaultProviderMemory or RedisCache provider
System__Storage__Cache__Providers__Redis__ConnectionStringredis:6379Redis address
System__RateLimit__DefaultRequestsPerMinute60Per-agent rate limit
System__CircuitBreaker__FailureThreshold5Failures before circuit opens
Security__AgentAuth__ProviderSelfSigned or JwtAuth provider
Security__AgentAuth__Jwt__Issuerhttps://auth.example.comJWT issuer
Security__AgentAuth__Jwt__Audiencevectra-gatewayJWT audience
Security__AgentAuth__Jwt__SecretKeyyour-keyJWT signing key
Policy__EnabledtrueEnable policy engine
Policy__DefaultProviderInternal or OpaPolicy provider
Policy__Providers__Internal__Directory/policiesPolicy files directory
Policy__Providers__Opa__BaseUrlhttp://opa:8181OPA server URL
Semantic__EnabledfalseEnable semantic analysis
Semantic__DefaultProviderInternalSemantic provider
Semantic__Providers__OpenAi__ApiKeysk-...OpenAI API key
HumanInTheLoop__EnabledtrueEnable HITL
HumanInTheLoop__Threshold0.8Risk score HITL trigger
HumanInTheLoop__TimeoutSeconds3600HITL request TTL
HumanInTheLoop__NotificationWebhookUrlhttps://hooks.example.com/...HITL webhook
Observability__Logging__DefaultLogLevelInformationLog level
Observability__Logging__Seq__EnabledtrueEnable Seq sink
Observability__Logging__Seq__ServerUrlhttp://seq:5341Seq server URL
SecretManagement__DefaultProviderAzureKeyVaultSecret provider
SecretManagement__Providers__AzureKeyVault__VaultUrihttps://vault.vault.azure.net/Key Vault URI

Volume Mounts

Container Path (Linux)Container Path (Windows)Purpose
/dataC:\dataSQLite database file
/policiesC:\policiesJSON policy files
/app/logsC:\app\logsSerilog file sink output
/certsC:\certsTLS certificate (if HTTPS enabled)

Docker Compose

A full example with Redis, Seq, and OPA:

docker-compose.yml
services:

vectra:
image: vectra:1.0.0
build:
context: .
dockerfile: .docker/Dockerfile.linux
args:
APP_VERSION: "1.0.0"
ports:
- "7080:7080"
environment:
System__Storage__Database__DefaultProvider: Sqlite
System__Storage__Database__Providers__Sqlite__ConnectionString: "Data Source=/data/vectra.db"
System__Storage__Cache__DefaultProvider: Redis
System__Storage__Cache__Providers__Redis__ConnectionString: "redis:6379"
System__RateLimit__DefaultRequestsPerMinute: "60"
System__CircuitBreaker__FailureThreshold: "5"
Security__AgentAuth__Provider: SelfSigned
Policy__Enabled: "true"
Policy__DefaultProvider: Internal
Policy__Providers__Internal__Directory: /policies
HumanInTheLoop__Enabled: "true"
HumanInTheLoop__Threshold: "0.8"
HumanInTheLoop__TimeoutSeconds: "3600"
Observability__Logging__DefaultLogLevel: Information
Observability__Logging__Seq__Enabled: "true"
Observability__Logging__Seq__ServerUrl: http://seq:5341
volumes:
- vectra-data:/data
- ./policies:/policies:ro
- vectra-logs:/app/logs
depends_on:
- redis
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:7080/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s

redis:
image: redis:7-alpine
ports:
- "6379:6379"
restart: unless-stopped

seq:
image: datalust/seq:latest
ports:
- "5341:5341"
- "8080:80"
environment:
ACCEPT_EULA: "Y"
volumes:
- seq-data:/data
restart: unless-stopped

volumes:
vectra-data:
vectra-logs:
seq-data:

Start everything:

docker compose up -d

HTTPS in Docker

Mount your certificate and set the relevant environment variables:

docker run -d \
--name vectra \
-p 7080:7080 \
-p 7443:7443 \
-e System__Server__Https__Enabled=true \
-e System__Server__Https__Port=7443 \
-e System__Server__Https__Certificate__Path=/certs/vectra.pfx \
-e System__Server__Https__Certificate__Password=your-cert-password \
-v $(pwd)/certs:/certs:ro \
vectra:1.0.0

User Security

ImageRuns as
Dockerfile.linuxDefault (root in base image — see note below)
Dockerfile.windows-ltsc2022ContainerUser (least-privilege built-in account)
Dockerfile.windows-ltsc2025ContainerUser (least-privilege built-in account)
Linux containers and root

The Linux image currently runs as root. For production deployments, add a non-root user to Dockerfile.linux:

RUN addgroup --system vectra && adduser --system --ingroup vectra vectra
USER vectra

This should be placed before the ENTRYPOINT in the runtime stage.


Health Check

Vectra exposes a /health endpoint. Use it for Docker health checks and orchestrator readiness probes:

curl http://localhost:7080/health
# {"status":"Healthy","healthCheckDuration":"00:00:00.0023456"}