Docker Deployment
Run AltBase locally with Docker Compose, understand each container, and learn production deployment patterns for Kubernetes.
Prerequisites
- Docker Engine 24+ and Docker Compose v2
- At least 4 GB of RAM available for the containers
- Ports 3000, 5433, 6379, 4222, 8222, 10000, 10001, and 3003 available
Quick Start
git clone https://github.com/AltbaseDB/AltBaseDb.git
cd altbase
cp .env.example .env
docker compose -f docker/docker-compose.yml up
The AtlasDB API is available at http://localhost:3000 once all services pass their health checks.
Container Stack
The Compose file defines eight services. Six are infrastructure dependencies and two are observability services.
PostgreSQL 16
image: postgres:16-alpine
ports: ["5433:5432"]
The primary database. Runs with wal_level=logical enabled for CDC (Change Data Capture) and up to 10 replication slots with a 4 GB WAL retention limit.
Two logical databases are created:
| Database | Purpose |
|---|---|
atlas_control_plane | Organizations, projects, API keys, platform users, auth settings |
atlas_tenants | Tenant schemas (proj_{id}) with application data per project |
An init script (init-tenant-db.sql) runs on first boot to create the tenant database.
Redis 7
image: redis:7-alpine
ports: ["6379:6379"]
Used for distributed caching, session storage, rate limiting counters, and TUS upload state. Runs with append-only file persistence enabled.
NATS with JetStream
image: nats:2-alpine
ports: ["4222:4222", "8222:8222"]
The message broker for all async communication: CDC fan-out, workflow step dispatch, trigger evaluation, background jobs, and integration webhook delivery. JetStream is enabled for durable streams and at-least-once delivery.
Port 8222 exposes the NATS HTTP monitoring endpoint.
Azurite (Azure Storage Emulator)
image: mcr.microsoft.com/azure-storage/azurite
ports: ["10000:10000", "10001:10001"]
Local emulator for Azure Blob Storage. Used by the storage subsystem for bucket and object operations in development. In production, replace with S3, Azure Blob Storage, or a local filesystem backend.
Nango
image: nangohq/nango:latest
ports: ["3003:3003"]
OAuth proxy for 500+ SaaS integrations. Manages connection credentials, token refresh, and OAuth callback flows. Connects to the same PostgreSQL instance (separate nango database).
Requires the NANGO_ENCRYPTION_KEY environment variable for credential encryption.
OpenTelemetry Collector
image: otel/opentelemetry-collector-contrib:latest
ports: ["4317:4317"]
Receives traces from the Atlas server via OTLP and forwards them to Jaeger for visualization.
Jaeger
image: jaegertracing/all-in-one:latest
ports: ["16686:16686"]
Distributed tracing UI available at http://localhost:16686. Useful for debugging request flows across crates and services.
AtlasDB (Main Service)
build:
context: ..
dockerfile: docker/Dockerfile
ports: ["3000:3000"]
The single Rust binary containing the full platform. Depends on PostgreSQL, Redis, NATS, Nango, and OTel collector being healthy before starting.
Health Checks
Every service includes a health check. The AtlasDB binary exposes two endpoints:
| Endpoint | Purpose |
|---|---|
GET /health/live | Liveness probe -- process is running |
GET /health/ready | Readiness probe -- database and dependencies connected |
curl http://localhost:3000/health/live
# 200 OK
curl http://localhost:3000/health/ready
# 200 OK (or 503 if dependencies are unavailable)
Dockerfile
The production image is a multi-stage build using cargo-chef for fast incremental builds:
| Stage | Base | What It Does |
|---|---|---|
| Chef planner | rust:latest | Creates a recipe.json of Cargo.toml dependencies |
| Dependency cook | rust:latest | Compiles only dependencies (cached layer) |
| Source build | rust:latest | Compiles the Rust binary (atlas-server) in release mode |
| Dashboard build | node:20-bookworm-slim | Builds the React dashboard to static files |
| Runtime | debian:bookworm-slim | Minimal runtime with ca-certificates, libssl3, and embedded NATS server |
The final image:
- Runs as a non-root
atlasuser - Copies the compiled binary and dashboard static files
- Exposes port 4000 (overridable via
ATLAS_PORT; Docker Compose overrides to 3000) - Includes a
HEALTHCHECKthat polls/health/liveevery 30 seconds
Starting Only Infrastructure
During development you often want to run the Rust server natively with cargo run while keeping the infrastructure containers running:
docker compose -f docker/docker-compose.yml up postgres redis nats azurite nango
Or use the bootstrap script:
./scripts/bootstrap.sh --start-infra
Then in another terminal:
cargo run -p atlas-server
Production Considerations
Resource Limits
Set memory and CPU limits for each container in production:
services:
atlas:
deploy:
resources:
limits:
memory: 512M
cpus: "2.0"
The AtlasDB binary typically uses 50-100 MB of memory at baseline.
Backup
- PostgreSQL: Use
pg_dumpor continuous archiving with WAL-G for point-in-time recovery - Redis: RDB snapshots are enabled by default; consider enabling AOF for durability
- NATS JetStream: Data is stored on the NATS volume; back up the
/datadirectory - Object Storage: In production, use a managed S3 or Azure Blob service with built-in redundancy
Monitoring
- NATS exposes metrics at
http://localhost:8222/varz - PostgreSQL can be monitored with
pg_stat_statementsand Prometheus exporters - The AtlasDB server logs structured JSON to stdout
Kubernetes Deployment
For production workloads, deploy to Kubernetes with the following resource types:
| Resource | Component | Notes |
|---|---|---|
Deployment | AtlasDB (N replicas) | Stateless; scale horizontally |
StatefulSet | PostgreSQL (1 primary + replicas) | Persistent volumes for data |
Deployment | Redis (1 replica) | Or use a managed Redis service |
Deployment | NATS (1+ replicas with JetStream) | Persistent volumes for streams |
Ingress | TLS termination | Route to the AtlasDB Service |
ConfigMap | Non-sensitive configuration | Database URLs, feature flags |
Secret | Sensitive configuration | Passwords, API keys, encryption keys |
Minimal Manifest Pattern
apiVersion: apps/v1
kind: Deployment
metadata:
name: atlasdb
namespace: atlasdb
spec:
replicas: 2
selector:
matchLabels:
app: atlasdb
template:
spec:
containers:
- name: atlasdb
image: altbase/atlasdb:latest
ports:
- containerPort: 4000
envFrom:
- configMapRef:
name: atlasdb-config
- secretRef:
name: atlasdb-secrets
livenessProbe:
httpGet:
path: /health/live
port: 4000
readinessProbe:
httpGet:
path: /health/ready
port: 4000
The AtlasDB binary is stateless (all state lives in PostgreSQL, Redis, and NATS), so horizontal scaling is straightforward.