This guide explains the Docker Compose configuration for ImaForm, including all services, their dependencies, and configuration options.
Purpose: React-based frontend application
Configuration:
frontend:
build:
context: ../frontend
dockerfile: ../docker/frontend/Dockerfile
target: runner
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_API_URL=${API_URL:-http://localhost:8000}
- NEXT_PUBLIC_WS_URL=${WS_URL:-ws://localhost:8000}
- NODE_ENV=${NODE_ENV:-production}
depends_on:
backend:
condition: service_healthy
volumes:
- ../storage:/storage:ro
restart: unless-stopped
networks:
- imaform-network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sEnvironment Variables:
NEXT_PUBLIC_API_URL: Backend API URLNEXT_PUBLIC_WS_URL: WebSocket URLNODE_ENV: Node environment (development/production)
Health Check: HTTP GET to /api/health endpoint
Purpose: Python-based REST API backend
Configuration:
backend:
build:
context: ../backend
dockerfile: ../docker/backend/Dockerfile
ports:
- "8000:8000"
environment:
- DATABASE_URL=${DATABASE_URL:-postgresql+asyncpg://postgres:postgres@postgres:5432/imaform}
- REDIS_URL=${REDIS_URL:-redis://redis:6379/0}
- GEOMETRY_SERVICE_URL=${GEOMETRY_SERVICE_URL:-http://geometry:8001}
- SECRET_KEY=${SECRET_KEY:-your-secret-key-change-in-production}
- ENVIRONMENT=${ENVIRONMENT:-development}
- CORS_ORIGINS=${CORS_ORIGINS:-http://localhost:3000,http://localhost}
- STORAGE_PATH=/storage
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
geometry:
condition: service_healthy
volumes:
- ../storage:/storage
- backend_cache:/app/cache
restart: unless-stopped
networks:
- imaform-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sEnvironment Variables:
DATABASE_URL: PostgreSQL connection stringREDIS_URL: Redis connection stringGEOMETRY_SERVICE_URL: Geometry service URLSECRET_KEY: JWT secret keyENVIRONMENT: Application environmentCORS_ORIGINS: Allowed CORS originsSTORAGE_PATH: Storage directory path
Health Check: HTTP GET to /api/v1/health endpoint
Purpose: SDF/voxel-based geometry generation engine
Configuration:
geometry:
build:
context: ../geometry
dockerfile: ../docker/geometry/Dockerfile
ports:
- "8001:8001"
environment:
- CUDA_VISIBLE_DEVICES=${CUDA_VISIBLE_DEVICES:-0}
- PYTHONUNBUFFERED=1
volumes:
- geometry_cache:/app/cache
restart: unless-stopped
networks:
- imaform-network
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8001/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sEnvironment Variables:
CUDA_VISIBLE_DEVICES: GPU device(s) to use
GPU Configuration:
- Requires NVIDIA Docker runtime
- Automatically reserves 1 GPU
- Set
CUDA_VISIBLE_DEVICESto control GPU usage
Health Check: HTTP GET to /health endpoint
Purpose: Relational database
Configuration:
postgres:
image: postgres:16-alpine
environment:
- POSTGRES_USER=${POSTGRES_USER:-postgres}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-postgres}
- POSTGRES_DB=${POSTGRES_DB:-imaform}
- POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
ports:
- "${POSTGRES_PORT:-5432}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
networks:
- imaform-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-imaform}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10sEnvironment Variables:
POSTGRES_USER: Database userPOSTGRES_PASSWORD: Database passwordPOSTGRES_DB: Database namePOSTGRES_INITDB_ARGS: Database initialization arguments
Health Check: pg_isready command
Purpose: Message broker and cache
Configuration:
redis:
image: redis:7-alpine
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-}
ports:
- "${REDIS_PORT:-6379}:6379"
volumes:
- redis_data:/data
restart: unless-stopped
networks:
- imaform-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10sEnvironment Variables:
REDIS_PASSWORD: Redis password (optional)
Health Check: redis-cli ping command
Purpose: Reverse proxy and load balancer
Configuration:
nginx:
image: nginx:1.25-alpine
ports:
- "${NGINX_HTTP_PORT:-80}:80"
- "${NGINX_HTTPS_PORT:-443}:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- ../storage:/storage:ro
- nginx_logs:/var/log/nginx
depends_on:
frontend:
condition: service_healthy
backend:
condition: service_healthy
restart: unless-stopped
networks:
- imaform-network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10sEnvironment Variables:
NGINX_HTTP_PORT: HTTP port (default: 80)NGINX_HTTPS_PORT: HTTPS port (default: 443)
Health Check: HTTP GET to /health endpoint
Purpose: Background task processing
Configuration:
celery-worker:
build:
context: ../backend
dockerfile: ../docker/backend/Dockerfile
command: celery -A app.tasks.celery_app worker --loglevel=info --concurrency=${CELERY_WORKER_CONCURRENCY:-2}
environment:
- DATABASE_URL=${DATABASE_URL:-postgresql+asyncpg://postgres:postgres@postgres:5432/imaform}
- REDIS_URL=${REDIS_URL:-redis://redis:6379/0}
- GEOMETRY_SERVICE_URL=${GEOMETRY_SERVICE_URL:-http://geometry:8001}
- SECRET_KEY=${SECRET_KEY:-your-secret-key-change-in-production}
- ENVIRONMENT=${ENVIRONMENT:-development}
- STORAGE_PATH=/storage
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
geometry:
condition: service_healthy
volumes:
- ../storage:/storage
- backend_cache:/app/cache
restart: unless-stopped
networks:
- imaform-network
healthcheck:
test: ["CMD-SHELL", "celery -A app.tasks.celery_app inspect ping"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sEnvironment Variables:
CELERY_WORKER_CONCURRENCY: Number of worker processes (default: 2)
Health Check: Celery inspect ping command
Purpose: Scheduled task execution
Configuration:
celery-beat:
build:
context: ../backend
dockerfile: ../docker/backend/Dockerfile
command: celery -A app.tasks.celery_app beat --loglevel=info
environment:
- DATABASE_URL=${DATABASE_URL:-postgresql+asyncpg://postgres:postgres@postgres:5432/imaform}
- REDIS_URL=${REDIS_URL:-redis://redis:6379/0}
- GEOMETRY_SERVICE_URL=${GEOMETRY_SERVICE_URL:-http://geometry:8001}
- SECRET_KEY=${SECRET_KEY:-your-secret-key-change-in-production}
- ENVIRONMENT=${ENVIRONMENT:-development}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- backend_cache:/app/cache
restart: unless-stopped
networks:
- imaform-network
healthcheck:
test: ["CMD-SHELL", "celery -A app.tasks.celery_app inspect ping"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sHealth Check: Celery inspect ping command
Type: Bridge network Purpose: Internal communication between services Isolation: Services on this network can communicate with each other
| Volume | Purpose | Service |
|---|---|---|
postgres_data |
PostgreSQL data storage | postgres |
redis_data |
Redis data storage | redis |
backend_cache |
Backend cache | backend, celery-worker, celery-beat |
geometry_cache |
Geometry engine cache | geometry |
nginx_logs |
Nginx access/error logs | nginx |
| Path | Purpose | Services |
|---|---|---|
../storage |
Shared storage for uploads/exports | frontend, backend, celery-worker, nginx |
./nginx/nginx.conf |
Nginx configuration | nginx |
./nginx/ssl |
SSL certificates | nginx |
frontend → backend → postgres
→ redis
→ geometry
backend → postgres
→ redis
→ geometry
celery-worker → postgres
→ redis
→ geometry
celery-beat → postgres
→ redis
nginx → frontend
→ backend
Services wait for dependencies to be healthy before starting:
- Frontend waits for backend to be healthy
- Backend waits for postgres, redis, and geometry to be healthy
- Celery services wait for postgres, redis, and geometry to be healthy
- Nginx waits for frontend and backend to be healthy
SECRET_KEY: JWT secret key (generate withopenssl rand -hex 32)
| Variable | Default | Description |
|---|---|---|
API_URL |
http://localhost:8000 |
Backend API URL |
WS_URL |
ws://localhost:8000 |
WebSocket URL |
NODE_ENV |
production |
Node environment |
DATABASE_URL |
postgresql+asyncpg://postgres:postgres@postgres:5432/imaform |
PostgreSQL connection string |
REDIS_URL |
redis://redis:6379/0 |
Redis connection string |
GEOMETRY_SERVICE_URL |
http://geometry:8001 |
Geometry service URL |
ENVIRONMENT |
development |
Application environment |
CORS_ORIGINS |
http://localhost:3000,http://localhost |
Allowed CORS origins |
STORAGE_PATH |
/storage |
Storage directory path |
POSTGRES_USER |
postgres |
PostgreSQL user |
POSTGRES_PASSWORD |
postgres |
PostgreSQL password |
POSTGRES_DB |
imaform |
PostgreSQL database name |
POSTGRES_PORT |
5432 |
PostgreSQL port |
REDIS_PASSWORD |
(empty) | Redis password |
REDIS_PORT |
6379 |
Redis port |
NGINX_HTTP_PORT |
80 |
HTTP port |
NGINX_HTTPS_PORT |
443 |
HTTPS port |
CELERY_WORKER_CONCURRENCY |
2 |
Celery worker concurrency |
CUDA_VISIBLE_DEVICES |
0 |
GPU device(s) to use |
Services can be scaled horizontally using Docker Compose:
# Scale backend to 3 instances
docker compose up -d --scale backend=3
# Scale celery-worker to 4 instances
docker compose up -d --scale celery-worker=4Note: Nginx load balancing will distribute traffic across scaled instances.
Increase resources in docker-compose.yml:
services:
backend:
deploy:
resources:
limits:
cpus: '2.0'
memory: 4G
reservations:
cpus: '1.0'
memory: 2G