Deployment Guide
Zero-Downtime Deployment
Jiji ensures zero downtime during deployments through a rolling update process:
┌─────────────────────────────────────────────────────────────────┐
│ Zero-Downtime Flow │
│ │
│ 1. Old Container Running ──▶ Traffic served │
│ │
│ 2. Rename Old Container ──▶ Keep running as backup │
│ │
│ 3. New Container Starts ──▶ Old still serving │
│ │
│ 4. Health Checks Pass ──▶ New marked healthy │
│ │
│ 5. Proxy Routes to New ──▶ Traffic switches │
│ │
│ 6. Old Container Stops ──▶ Cleanup complete │
│ │
│ If health checks fail: │
│ ──▶ Old container continues serving, new container removed │
└─────────────────────────────────────────────────────────────────┘Health Checks
Health checks are critical for zero-downtime deployments.
HTTP Health Check
services:
api:
proxy:
healthcheck:
path: /health
interval: 10s
timeout: 5s
deploy_timeout: 60s| Option | Description |
|---|---|
path | HTTP endpoint to check (must return 2xx) |
interval | Time between checks |
timeout | Max time to wait for response |
deploy_timeout | Max time to wait for container to become healthy |
Command Health Check
For non-HTTP services:
services:
worker:
proxy:
healthcheck:
cmd: "test -f /tmp/ready"
cmd_runtime: docker # docker or podman
interval: 10s
timeout: 5s
deploy_timeout: 60sHealth Status Values
Containers can have these health statuses:
healthy- Passing health checksdegraded- Intermittent failuresunhealthy- Consistently failingunknown- No check run yet
Deployment Strategies
Full Deploy
Deploy all services to all hosts:
jiji deploy --buildTargeted Deploy
Deploy specific services:
jiji deploy -S api
jiji deploy -S "api,worker"
jiji deploy -S "web*" # Wildcard matchingDeploy to specific hosts:
jiji deploy -H web1
jiji deploy -H "prod*" # Wildcard matchingCombine both:
jiji deploy -S api -H "prod*"Version Pinning
Deploy a specific version:
jiji deploy --version v1.2.3Build with version tag:
jiji build --version v1.2.3
jiji deploy --version v1.2.3Skip Confirmation
For CI/CD pipelines:
jiji deploy -y # Skip confirmation prompt
jiji deploy --yes --buildRollback
If something goes wrong, deploy a previous version:
# Check available versions
jiji server exec "docker images | grep myapp"
# Deploy previous version
jiji deploy --version v1.2.2Deployment Locks
Prevent concurrent deployments with locking:
Acquire Lock
jiji lock acquire "Deploying v1.2.3"
jiji lock acquire "Deploying v1.2.3" --timeout 300 # Timeout in secondsRelease Lock
jiji lock releaseCheck Lock Status
jiji lock status
jiji lock status --json
jiji lock show # Detailed infoForce Acquire
If a lock is stuck (e.g., from a failed deployment):
jiji lock acquire "Taking over stuck deployment" --forceRecommended Workflow
# Acquire lock before deploy
jiji lock acquire "Deploying v1.2.3"
# Deploy
jiji deploy --build
# Release lock
jiji lock releaseResource Management
CPU Limits
services:
api:
cpus: 2 # 2 CPU cores
cpus: 0.5 # Half a CPU core
cpus: 1.5 # 1.5 CPU coresMemory Limits
services:
api:
memory: "512m" # 512 MB
memory: "1g" # 1 GB
memory: "2gb" # 2 GBSupported units: b, k, m, g, kb, mb, gb
GPU Access
services:
ml-worker:
gpus: "all" # All available GPUs
gpus: "0" # GPU 0 only
gpus: "0,1" # GPUs 0 and 1Device Mapping
services:
video-processor:
devices:
- "/dev/video0"
- "/dev/snd:/dev/snd:rwm"Linux Capabilities
services:
vpn-client:
cap_add:
- NET_ADMIN
- SYS_MODULEOr for full privileged access:
services:
system-tool:
privileged: trueMulti-Architecture Support
Jiji supports deploying to mixed architecture clusters (amd64 and arm64).
Configuration
servers:
x86-server:
host: amd64.example.com
arch: amd64
arm-server:
host: arm64.example.com
arch: arm64
services:
api:
hosts:
- x86-server
- arm-server
build:
context: .Jiji automatically:
- Builds the correct architecture for each server
- Pulls architecture-specific images
- Handles multi-arch deployments transparently
Stateful Services
For services that can’t run multiple instances simultaneously (databases, etc.):
services:
postgres:
stop_first: true # Stop old before starting new
volumes:
- /data/postgres:/var/lib/postgresql/dataWith stop_first: true:
- Old container stops first
- New container starts
- Brief downtime during transition
File and Directory Transfers
Transfer Files (Simple)
services:
api:
files:
- ./config.json:/app/config.json
- ./secrets.env:/app/.env:600 # With permissionsTransfer Files (Detailed)
services:
api:
files:
- local: config/secret.key
remote: /etc/app/secret.key
mode: "0600"
owner: "nginx:nginx"
options: "ro"Transfer Directories
services:
api:
directories:
- ./templates:/app/templates
- local: logs
remote: /var/log/app
mode: "0755"
owner: "app:app"Volume Mounts
Persist data across deployments:
services:
db:
volumes:
- /data/postgres:/var/lib/postgresql/data
- /config:/app/config:ro # Read-only
- app_storage:/app/data # Named volumeNote: Named volumes (those not starting with
/or./) are automatically prefixed with the service name to prevent conflicts between services. For example,app_storagebecomesdb-app_storagewhen used by thedbservice.
Environment Variables
Clear Variables
Non-sensitive configuration:
services:
api:
environment:
clear:
NODE_ENV: production
LOG_LEVEL: info
PORT: "3000"Secret Variables
Sensitive values loaded from .env files:
services:
api:
environment:
secrets:
- DATABASE_URL
- API_KEY
- JWT_SECRETCreate a .env file in your project root:
# .env (or .env.production for environment-specific)
DATABASE_URL=postgres://user:pass@host:5432/db
API_KEY=secret123
JWT_SECRET=your-jwt-secretDeploy (secrets are automatically loaded from .env):
jiji deploy
jiji deploy -e production # Uses .env.productionView Configured Secrets
jiji secrets print
jiji secrets print -e production
jiji secrets print --show-values # Reveal actual valuesHost Environment Fallback
To use host environment variables when not found in .env:
jiji --host-env deployImage Retention
Configure how many old images to keep per service:
services:
api:
retain: 5 # Keep 5 versions (default: 3)Manual cleanup:
jiji services prune
jiji services prune -S api --retain 3Pre-Deployment Checklist
Before deploying to production:
- Test locally - Run your containers locally first
- Check configuration - Review your deploy.yml
- Review changes - Know what you’re deploying
- Check server connectivity -
jiji server exec "echo ok" - Verify registry access -
jiji registry login - Check secrets -
jiji secrets print - Acquire lock -
jiji lock acquire "Deploying vX.Y.Z"
Post-Deployment Verification
After deploying:
# Check service logs
jiji services logs -S api --since 5m
# Verify containers running
jiji server exec "docker ps"
# Check health endpoints
jiji server exec "curl localhost:3000/health"
# Monitor proxy logs
jiji proxy logs --since 5m
# Check network status
jiji network status
# View DNS records
jiji network dnsCleanup
Remove old images to free disk space:
jiji services prune
jiji services prune --retain 3 # Keep 3 versions
jiji services prune -S api # Specific serviceClean up stale DNS records:
jiji network gc --forceCI/CD Integration
For automated deployments, use the -y flag and proper locking:
#!/bin/bash
set -e
# Acquire lock
jiji lock acquire "CI Deploy: $CI_COMMIT_SHA"
# Deploy
jiji deploy --build -y -e production
# Release lock
jiji lock releaseSee the CI/CD Integration guide for detailed examples.