Docker Reference¶
Junjo Server is distributed as three Docker images that work together to provide a complete observability platform for AI workflows. This page provides detailed reference information for deploying and configuring these services.
Quick Start: For a ready-to-use setup, see the Junjo Server Bare-Bones Template. For a complete production example with reverse proxy and HTTPS, see the Junjo Server Deployment Example. More details in Junjo Server Deployment.
Docker Images¶
Backend Service¶
Image: mdrideout/junjo-server-backend
The backend service provides the HTTP API, authentication, and data processing capabilities. It uses SQLite for metadata storage and DuckDB for analytical queries.
Ports:
1323
- HTTP API server (public)50053
- Internal gRPC for service communication (internal)
Volumes:
/dbdata/sqlite
- SQLite database directory (persistent)/dbdata/duckdb
- DuckDB database directory (persistent)
Notes:
Requires root user or appropriate permissions for database write operations
Polls the ingestion service for new telemetry data
Processes and indexes traces for querying via the web UI
Ingestion Service¶
Image: mdrideout/junjo-server-ingestion-service
The ingestion service provides high-throughput OpenTelemetry data reception using BadgerDB as a write-ahead log. This decoupled architecture ensures telemetry data is never lost, even under heavy load.
Ports:
50051
- OpenTelemetry gRPC ingestion endpoint (public, your applications connect here)50052
- Internal gRPC for backend polling (internal)
Volumes:
/dbdata/badgerdb
- BadgerDB write-ahead log directory (persistent)
Notes:
This is the primary endpoint where your Junjo workflows send telemetry
Uses BadgerDB for durable, high-performance data ingestion
Backend service polls this service to retrieve new data
Frontend Service¶
Image: mdrideout/junjo-server-frontend
The frontend service provides the interactive web UI for visualizing and debugging AI workflows.
Ports:
80
- Web UI HTTP server (public)
Notes:
Static web application that communicates with the backend API
Requires backend service to be running and healthy
Serves interactive graph visualizations and state debugging tools
Complete Docker Compose Configuration¶
Production-Ready Configuration¶
This configuration includes all three services with best practices for production deployment:
services:
# Backend API and data processing service
junjo-server-backend:
image: mdrideout/junjo-server-backend:latest
container_name: junjo-server-backend
restart: unless-stopped
ports:
- "1323:1323" # HTTP API (public)
- "50053:50053" # Internal gRPC (backend communication)
volumes:
# Persistent database storage
- ./dbdata/sqlite:/dbdata/sqlite
- ./dbdata/duckdb:/dbdata/duckdb
environment:
# Environment (production|development)
- JUNJO_ENV=${JUNJO_ENV:-production}
# CORS origins (comma-separated)
- JUNJO_ALLOW_ORIGINS=${JUNJO_ALLOW_ORIGINS}
# Session secret for authentication (generate with: openssl rand -hex 32)
- JUNJO_SESSION_SECRET=${JUNJO_SESSION_SECRET}
# Production authentication domain
- JUNJO_PROD_AUTH_DOMAIN=${JUNJO_PROD_AUTH_DOMAIN}
networks:
- junjo-network
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:1323/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# OpenTelemetry data ingestion service
junjo-server-ingestion:
image: mdrideout/junjo-server-ingestion-service:latest
container_name: junjo-server-ingestion
restart: unless-stopped
ports:
- "50051:50051" # OTel gRPC ingestion (public, your apps connect here)
- "50052:50052" # Internal gRPC (backend polling)
volumes:
# BadgerDB write-ahead log
- ./dbdata/badgerdb:/dbdata/badgerdb
environment:
# API key for authentication (generate in web UI)
- JUNJO_SERVER_API_KEY=${JUNJO_SERVER_API_KEY}
networks:
- junjo-network
depends_on:
junjo-server-backend:
condition: service_healthy # Wait for backend server to be healthy before starting
healthcheck:
test: ["CMD", "grpc_health_probe", "-addr=:50051"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# Web UI for visualization and debugging
junjo-server-frontend:
image: mdrideout/junjo-server-frontend:latest
container_name: junjo-server-frontend
restart: unless-stopped
ports:
- "5153:80" # Web UI
environment:
# Backend API URL (adjust for your deployment)
- VITE_API_URL=${VITE_API_URL:-http://localhost:1323}
networks:
- junjo-network
depends_on:
junjo-server-backend:
condition: service_healthy
junjo-server-ingestion:
condition: service_healthy
networks:
junjo-network:
driver: bridge
Development Configuration¶
For local development, you can use a simpler configuration:
services:
junjo-server-backend:
image: mdrideout/junjo-server-backend:latest
ports:
- "1323:1323"
- "50053:50053"
volumes:
- ./.dbdata/sqlite:/dbdata/sqlite
- ./.dbdata/duckdb:/dbdata/duckdb
environment:
- JUNJO_ENV=development
- JUNJO_ALLOW_ORIGINS=http://localhost:5153
networks:
- junjo-network
junjo-server-ingestion:
image: mdrideout/junjo-server-ingestion-service:latest
ports:
- "50051:50051"
- "50052:50052"
volumes:
- ./.dbdata/badgerdb:/dbdata/badgerdb
networks:
- junjo-network
junjo-server-frontend:
image: mdrideout/junjo-server-frontend:latest
ports:
- "5153:80"
environment:
- VITE_API_URL=http://localhost:1323
networks:
- junjo-network
networks:
junjo-network:
driver: bridge
Environment Variables Reference¶
Backend Service¶
JUNJO_ENV
Required. Environment mode:
production
ordevelopment
Default: None
Example:
JUNJO_ENV=production
JUNJO_ALLOW_ORIGINS
Required. Comma-separated list of allowed CORS origins for API requests
Default: None
Example:
JUNJO_ALLOW_ORIGINS=https://junjo.example.com,https://www.example.com
JUNJO_SESSION_SECRET
Required for production. Secret key for session management and JWT tokens
Default: None
Example:
JUNJO_SESSION_SECRET=a1b2c3d4e5f6...
(64 character hex string)Generate with:
openssl rand -hex 32
JUNJO_PROD_AUTH_DOMAIN
Required for production. The primary domain for authentication cookies
Default: None
Example:
JUNJO_PROD_AUTH_DOMAIN=junjo.example.com
JUNJO_BUILD_TARGET
Optional. Build target for development purposes
Default:
production
Example:
JUNJO_BUILD_TARGET=development
Ingestion Service¶
JUNJO_SERVER_API_KEY
Required. API key for authenticating telemetry ingestion requests
Default: None
Example:
JUNJO_SERVER_API_KEY=js_1234567890abcdef...
Generate: Create in the Junjo Server web UI under Settings → API Keys
Frontend Service¶
VITE_API_URL
Optional. Backend API URL for the frontend to connect to
Default:
http://localhost:1323
(development)Example:
VITE_API_URL=https://api.junjo.example.com
Note: In production with reverse proxy, this may be a relative path
Volume Mounts¶
All three services require persistent storage for their databases. The recommended approach is to use either local directories or block storage volumes.
Local Directory Structure¶
.
├── docker-compose.yml
├── .env
└── dbdata/
├── sqlite/ # Backend metadata
├── duckdb/ # Backend analytics
└── badgerdb/ # Ingestion WAL
Create directories:
mkdir -p dbdata/{sqlite,duckdb,badgerdb}
chmod -R 755 dbdata
Block Storage (Production)¶
For production deployments, mount block storage at a consistent location:
# Example: Mount block storage
sudo mkfs.ext4 /dev/disk/by-id/scsi-0DO_Volume_junjo-data
sudo mkdir -p /mnt/junjo-data
sudo mount -o defaults,nofail /dev/disk/by-id/scsi-0DO_Volume_junjo-data /mnt/junjo-data
# Create database directories
sudo mkdir -p /mnt/junjo-data/{sqlite,duckdb,badgerdb}
sudo chown -R $USER:$USER /mnt/junjo-data
Update volume paths in docker-compose.yml:
volumes:
- /mnt/junjo-data/sqlite:/dbdata/sqlite
- /mnt/junjo-data/duckdb:/dbdata/duckdb
- /mnt/junjo-data/badgerdb:/dbdata/badgerdb
Port Mappings¶
Internal Communication¶
Services communicate internally via the Docker network. These ports do not need to be exposed to the host:
Backend (1323) ←→ Frontend
Backend (50053) ←→ Ingestion (50052)
External Access¶
These ports need to be accessible:
Development:
Frontend:
http://localhost:5153
(Web UI)Backend API:
http://localhost:1323
(Optional, usually only accessed by frontend)Ingestion:
localhost:50051
(Your applications connect here)
Production (with reverse proxy):
Frontend:
https://junjo.example.com
(Web UI)Backend API:
https://api.junjo.example.com
(API)Ingestion:
grpc.junjo.example.com:443
(gRPC with TLS)
See Junjo Server Deployment for production deployment examples with Caddy reverse proxy.
Resource Requirements¶
Junjo Server is designed to run on minimal resources:
Minimum:
CPU: 1 shared vCPU
RAM: 1 GB
Storage: 10 GB (more for long-term trace retention)
Recommended for Production:
CPU: 1-2 dedicated vCPUs
RAM: 2-4 GB
Storage: 25+ GB on block storage
Network: 1 Gbps
Database Sizes¶
BadgerDB (Ingestion): Write-ahead log, periodically compacted
SQLite (Backend): Metadata and indexes, grows slowly
DuckDB (Backend): Analytical data, grows with trace retention
Network Configuration¶
Docker Network¶
All services should run on the same Docker network for internal communication:
networks:
junjo-network:
driver: bridge
Firewall Rules¶
If using a firewall, allow these ports:
1323/tcp
- Backend API (if accessing directly)5153/tcp
- Frontend web UI50051/tcp
- Ingestion gRPC endpoint443/tcp
- HTTPS (if using reverse proxy)80/tcp
- HTTP (for Let’s Encrypt challenges)
Production Deployment¶
Reverse Proxy Setup¶
For production, use a reverse proxy like Caddy or Nginx to provide:
Automatic HTTPS with Let’s Encrypt
Subdomain routing
Load balancing (if scaling horizontally)
Example Caddyfile:
# Web UI
junjo.example.com {
reverse_proxy junjo-server-frontend:80
}
# Backend API
api.junjo.example.com {
reverse_proxy junjo-server-backend:1323
}
# Ingestion gRPC
grpc.junjo.example.com {
reverse_proxy h2c://junjo-server-ingestion:50051
}
See the Junjo Server Deployment Example for a complete production setup.
Backup and Recovery¶
Backup all three database directories regularly:
# Backup script example
tar -czf junjo-backup-$(date +%Y%m%d).tar.gz \
dbdata/sqlite \
dbdata/duckdb \
dbdata/badgerdb
To restore, stop services, extract backup, and restart:
docker compose down
tar -xzf junjo-backup-20241012.tar.gz
docker compose up -d
Monitoring¶
Monitor these key metrics:
Disk usage: Database directories
Memory usage: Each service container
Network traffic: Port 50051 (ingestion load)
API response time: Backend health endpoint
Error logs:
docker compose logs
Health Checks¶
Services include health check endpoints:
Backend:
http://localhost:1323/health
Ingestion: gRPC health probe on port 50051
Example monitoring with curl:
# Check backend health
curl http://localhost:1323/health
# Check all services
docker compose ps
Scaling Considerations¶
Horizontal Scaling¶
For high-volume deployments:
Ingestion Service: Can run multiple instances behind a load balancer
Backend Service: Can run multiple instances with shared database volumes
Frontend Service: Static assets, easily cached or CDN-distributed
Example multi-instance configuration:
services:
junjo-server-ingestion:
image: mdrideout/junjo-server-ingestion-service:latest
deploy:
replicas: 3
# ... rest of configuration
Vertical Scaling¶
For most deployments, vertical scaling is sufficient:
Increase CPU/RAM allocation
Use faster disk (NVMe SSDs)
Increase Docker memory limits
services:
junjo-server-backend:
# ... existing config
deploy:
resources:
limits:
cpus: '2'
memory: 4G
reservations:
cpus: '1'
memory: 2G
Troubleshooting¶
Service Won’t Start¶
Check logs for specific errors:
docker compose logs junjo-server-backend
docker compose logs junjo-server-ingestion
docker compose logs junjo-server-frontend
Common issues:
Missing environment variables in
.env
Port conflicts (check with
netstat -tlnp
)Permission issues with volume mounts
Network not created (
docker network create junjo-network
)
High Memory Usage¶
If services consume excessive memory:
Check BadgerDB size (
du -sh dbdata/badgerdb
)Implement trace retention policies
Increase disk swap if needed
Add memory limits to docker-compose.yml
Cannot Connect to Ingestion¶
If applications can’t send telemetry:
Verify port 50051 is accessible:
telnet localhost 50051
Check firewall rules
Verify API key in application matches server
Check ingestion service logs for auth errors
API Errors¶
If the web UI shows API errors:
Check CORS settings in backend (
JUNJO_ALLOW_ORIGINS
)Verify frontend can reach backend API
Check backend logs for specific errors
Verify session secret is set in production
Next Steps¶
See Junjo Server Intro for setup and configuration
Review Junjo Server Deployment for production deployment examples
Explore OpenTelemetry Integration for application instrumentation