Docker Compose Deployment
Docker Compose provides the simplest way to deploy Terragnos Core on a single host. This guide covers the complete setup, configuration, and operational procedures for a Compose-based deployment.
Prerequisites
- Docker Engine 24+ with the
docker composeplugin - At least 8 GB RAM, 4 vCPUs, and 20 GB free disk space
- Network access to pull container images (or use pre-loaded images)
Quick Start
- Create a directory for your deployment:
mkdir terragnos-core
cd terragnos-core
- Create a
docker-compose.ymlfile:
version: '3.8'
services:
db:
image: postgis/postgis:16-3.4
environment:
POSTGRES_DB: terragnos
POSTGRES_USER: terragnos
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- terragnos-db-data:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U terragnos"]
interval: 10s
timeout: 5s
retries: 5
db-setup:
image: terragnos/core-db-setup:latest
environment:
DATABASE_URL: postgres://terragnos:${POSTGRES_PASSWORD}@db:5432/terragnos
profiles:
- setup
depends_on:
db:
condition: service_healthy
api:
image: terragnos/core-api:latest
environment:
DATABASE_URL: postgres://terragnos:${POSTGRES_PASSWORD}@db:5432/terragnos
AUTH_JWT_SECRET: ${AUTH_JWT_SECRET}
AUTH_DEFAULT_TENANT: ${AUTH_DEFAULT_TENANT:-default}
LICENSE_KEY: ${LICENSE_KEY}
LICENSE_PUBLIC_KEY: ${LICENSE_PUBLIC_KEY}
LICENSE_STORAGE_SECRET: ${LICENSE_STORAGE_SECRET}
REDIS_URL: ${REDIS_URL:-}
RATE_LIMIT_TTL: ${RATE_LIMIT_TTL:-60}
RATE_LIMIT_LIMIT: ${RATE_LIMIT_LIMIT:-120}
ports:
- "3000:3000"
depends_on:
db:
condition: service_healthy
restart: unless-stopped
worker:
image: terragnos/core-worker:latest
environment:
DATABASE_URL: postgres://terragnos:${POSTGRES_PASSWORD}@db:5432/terragnos
LICENSE_KEY: ${LICENSE_KEY}
LICENSE_PUBLIC_KEY: ${LICENSE_PUBLIC_KEY}
REDIS_URL: ${REDIS_URL:-}
depends_on:
db:
condition: service_healthy
api:
condition: service_started
restart: unless-stopped
volumes:
terragnos-db-data:
- Create a
.envfile:
# Database
POSTGRES_PASSWORD=your-secure-password
# Authentication
AUTH_JWT_SECRET=your-jwt-secret-minimum-32-characters
AUTH_DEFAULT_TENANT=default
# Licensing (provided by Terragnos)
LICENSE_PUBLIC_KEY=-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----
LICENSE_KEY=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
LICENSE_STORAGE_SECRET=optional-encryption-key
# Optional
REDIS_URL=redis://redis:6379
RATE_LIMIT_TTL=60
RATE_LIMIT_LIMIT=120
- Start the database and run migrations:
docker compose up -d db
docker compose --profile setup up db-setup
docker compose --profile setup down
- Start the API and worker:
docker compose up -d api worker
- Verify the deployment:
curl http://localhost:3000/v1/health/live
Service Configuration
Database Service
The db service runs PostgreSQL with PostGIS extensions. Key settings:
- Port: 5432 (exposed for direct access if needed)
- Volume:
terragnos-db-datapersists data across restarts - Health check: Ensures database is ready before other services start
API Service
The api service exposes the REST/GraphQL API. Key settings:
- Port: 3000 (exposed to host)
- Dependencies: Waits for database to be healthy
- Restart policy:
unless-stoppedfor automatic recovery
Worker Service
The worker service processes background jobs. Key settings:
- No exposed ports: Worker is internal-only
- Dependencies: Waits for database and API
- Restart policy:
unless-stoppedfor automatic recovery
Environment Variables
Required Variables
POSTGRES_PASSWORD– Database passwordAUTH_JWT_SECRET– Secret for JWT token signing (minimum 32 characters)DATABASE_URL– Full database connection string (auto-constructed from components)
Optional Variables
AUTH_DEFAULT_TENANT– Default tenant ID (default: "default")LICENSE_KEY/LICENSE_PUBLIC_KEY– License keys from TerragnosLICENSE_STORAGE_SECRET– Encryption key for license storageREDIS_URL– Redis connection string for cachingRATE_LIMIT_TTL– Rate limit time window in seconds (default: 60)RATE_LIMIT_LIMIT– Maximum requests per window (default: 120)LAYER_CACHE_TTL_SECONDS– GeoJSON/MVT cache TTL (default: 3600)LOG_LEVEL– Logging level (default: "info")
Operational Procedures
Viewing Logs
# All services
docker compose logs -f
# Specific service
docker compose logs -f api
docker compose logs -f worker
Restarting Services
# Restart all services
docker compose restart
# Restart specific service
docker compose restart api
Stopping Services
# Stop all services (keeps data)
docker compose down
# Stop and remove volumes (deletes data)
docker compose down --volumes
Updating Images
# Pull latest images
docker compose pull
# Restart services with new images
docker compose up -d
Database Backups
# Create backup
docker compose exec db pg_dump -U terragnos terragnos > backup.sql
# Restore backup
docker compose exec -T db psql -U terragnos terragnos < backup.sql
Scaling
For higher availability or performance, you can scale services:
# Scale API instances
docker compose up -d --scale api=3
# Scale worker instances
docker compose up -d --scale worker=2
Note: Ensure your load balancer distributes traffic across API instances.
Production Considerations
- Use secrets management – Store sensitive values in Docker secrets or external secret managers
- Enable HTTPS – Use a reverse proxy (nginx, Traefik) for TLS termination
- Set resource limits – Add
deploy.resourceslimits to prevent resource exhaustion - Configure logging – Use Docker logging drivers for centralized log aggregation
- Regular backups – Automate database backups
- Monitor health – Set up monitoring for
/v1/health/liveand/v1/health/readyendpoints - Update regularly – Keep container images updated for security patches
Troubleshooting
Services won't start
# Check logs
docker compose logs
# Verify environment variables
docker compose config
Database connection errors
# Check database is healthy
docker compose ps db
# Test connection
docker compose exec db psql -U terragnos -d terragnos
License errors
# Verify license is loaded
curl -H "Authorization: Bearer <token>" http://localhost:3000/v1/license
# Check environment variables
docker compose exec api env | grep LICENSE