Skip to main content

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 compose plugin
  • 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

  1. Create a directory for your deployment:
mkdir terragnos-core
cd terragnos-core
  1. Create a docker-compose.yml file:
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:
  1. Create a .env file:
# 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
  1. Start the database and run migrations:
docker compose up -d db
docker compose --profile setup up db-setup
docker compose --profile setup down
  1. Start the API and worker:
docker compose up -d api worker
  1. 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-data persists 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-stopped for 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-stopped for automatic recovery

Environment Variables

Required Variables

  • POSTGRES_PASSWORD – Database password
  • AUTH_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 Terragnos
  • LICENSE_STORAGE_SECRET – Encryption key for license storage
  • REDIS_URL – Redis connection string for caching
  • RATE_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

  1. Use secrets management – Store sensitive values in Docker secrets or external secret managers
  2. Enable HTTPS – Use a reverse proxy (nginx, Traefik) for TLS termination
  3. Set resource limits – Add deploy.resources limits to prevent resource exhaustion
  4. Configure logging – Use Docker logging drivers for centralized log aggregation
  5. Regular backups – Automate database backups
  6. Monitor health – Set up monitoring for /v1/health/live and /v1/health/ready endpoints
  7. 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