Stateful Docker Compose
This Docker Compose configuration runs all services including PostgreSQL, Redis, and MinIO as containers. This is the recommended setup for:
- VPS deployments (Digital Ocean, Linode, Hetzner)
- Local installations
- One-click deployments (Coolify, Dokploy)
When to Use This Configuration
Section titled “When to Use This Configuration”Use this configuration when:
- You want a simple, all-in-one deployment
- You don’t have access to managed databases or external storage
- You want to minimize external dependencies
- You’re deploying on a single VPS or local machine
For production environments with high availability requirements, consider using the Stateless Docker Compose configuration with managed databases instead.
Configuration File
Section titled “Configuration File”# Default Docker Compose - Builds images locally# Usage: docker compose up -d## This is the recommended way to run Isekai for self-hosting.# Includes MinIO for S3-compatible storage out of the box.
services: postgres: image: postgres:16-alpine environment: POSTGRES_USER: isekai POSTGRES_PASSWORD: isekai POSTGRES_DB: isekai ports: - '5433:5432' volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ['CMD-SHELL', 'pg_isready -U isekai'] interval: 10s timeout: 5s retries: 5 restart: unless-stopped
minio: image: minio/minio:latest container_name: isekai-minio command: server /data --console-address ":9001" ports: - '9000:9000' # S3 API - '9001:9001' # Web Console environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin volumes: - minio_data:/data healthcheck: test: ['CMD', 'mc', 'ready', 'local'] interval: 10s timeout: 5s retries: 5 restart: unless-stopped
# Creates the default bucket on startup minio-init: image: minio/mc:latest depends_on: minio: condition: service_healthy entrypoint: > /bin/sh -c " mc alias set myminio http://minio:9000 minioadmin minioadmin; mc mb myminio/isekai-uploads --ignore-existing; mc anonymous set download myminio/isekai-uploads; exit 0; "
redis: image: redis:7-alpine command: redis-server --appendonly yes --appendfsync everysec ports: - '6379:6379' volumes: - redis_data:/data healthcheck: test: ['CMD', 'redis-cli', 'ping'] interval: 10s timeout: 5s retries: 5 restart: unless-stopped
backend: build: context: . dockerfile: apps/isekai-backend/Dockerfile ports: - '4000:4000' environment: # Database & Cache DATABASE_URL: postgresql://isekai:isekai@postgres:5432/isekai REDIS_URL: redis://redis:6379
# URLs FRONTEND_URL: http://localhost:3000 PORT: 4000 NODE_ENV: production
# Security (CHANGE THESE!) SESSION_SECRET: ${SESSION_SECRET} ENCRYPTION_KEY: ${ENCRYPTION_KEY}
# DeviantArt OAuth (REQUIRED - Create your own app at deviantart.com/developers) DEVIANTART_CLIENT_ID: ${DEVIANTART_CLIENT_ID} DEVIANTART_CLIENT_SECRET: ${DEVIANTART_CLIENT_SECRET} DEVIANTART_REDIRECT_URI: ${DEVIANTART_REDIRECT_URI:-http://localhost:4000/api/auth/deviantart/callback}
# S3-Compatible Storage (defaults to local MinIO) S3_ENDPOINT: ${S3_ENDPOINT:-http://minio:9000} S3_REGION: ${S3_REGION:-us-east-1} S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-minioadmin} S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-minioadmin} S3_BUCKET_NAME: ${S3_BUCKET_NAME:-isekai-uploads} S3_PUBLIC_URL: ${S3_PUBLIC_URL:-http://localhost:9000/isekai-uploads} S3_FORCE_PATH_STYLE: ${S3_FORCE_PATH_STYLE:-true} env_file: - .env depends_on: postgres: condition: service_healthy redis: condition: service_healthy minio: condition: service_healthy restart: unless-stopped
publisher: build: context: . dockerfile: apps/isekai-publisher/Dockerfile ports: - '8000:8000' # Health check endpoint environment: # Database & Cache DATABASE_URL: postgresql://isekai:isekai@postgres:5432/isekai REDIS_URL: redis://redis:6379 NODE_ENV: production
# DeviantArt OAuth (same credentials as backend) DEVIANTART_CLIENT_ID: ${DEVIANTART_CLIENT_ID} DEVIANTART_CLIENT_SECRET: ${DEVIANTART_CLIENT_SECRET}
# S3-Compatible Storage (defaults to local MinIO) S3_ENDPOINT: ${S3_ENDPOINT:-http://minio:9000} S3_REGION: ${S3_REGION:-us-east-1} S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-minioadmin} S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-minioadmin} S3_BUCKET_NAME: ${S3_BUCKET_NAME:-isekai-uploads} S3_PUBLIC_URL: ${S3_PUBLIC_URL:-http://localhost:9000/isekai-uploads} S3_FORCE_PATH_STYLE: ${S3_FORCE_PATH_STYLE:-true}
# Publisher Configuration PUBLISHER_CONCURRENCY: ${PUBLISHER_CONCURRENCY:-5} PUBLISHER_MAX_ATTEMPTS: ${PUBLISHER_MAX_ATTEMPTS:-7} PUBLISHER_JOB_TIMEOUT_MS: ${PUBLISHER_JOB_TIMEOUT_MS:-600000} PUBLISHER_STALE_CHECK_INTERVAL_MS: ${PUBLISHER_STALE_CHECK_INTERVAL_MS:-60000} PUBLISHER_MAX_STALLED_COUNT: ${PUBLISHER_MAX_STALLED_COUNT:-2}
# Rate Limiter RATE_LIMITER_ENABLED: ${RATE_LIMITER_ENABLED:-true} RATE_LIMITER_BASE_DELAY_MS: ${RATE_LIMITER_BASE_DELAY_MS:-3000} RATE_LIMITER_MAX_DELAY_MS: ${RATE_LIMITER_MAX_DELAY_MS:-300000} RATE_LIMITER_JITTER_PERCENT: ${RATE_LIMITER_JITTER_PERCENT:-20} RATE_LIMITER_SUCCESS_DECREASE_FACTOR: ${RATE_LIMITER_SUCCESS_DECREASE_FACTOR:-0.9} RATE_LIMITER_FAILURE_INCREASE_FACTOR: ${RATE_LIMITER_FAILURE_INCREASE_FACTOR:-2.0}
# Circuit Breaker CIRCUIT_BREAKER_ENABLED: ${CIRCUIT_BREAKER_ENABLED:-true} CIRCUIT_BREAKER_THRESHOLD: ${CIRCUIT_BREAKER_THRESHOLD:-3} CIRCUIT_BREAKER_OPEN_DURATION_MS: ${CIRCUIT_BREAKER_OPEN_DURATION_MS:-300000} CIRCUIT_BREAKER_PERSIST_TO_REDIS: ${CIRCUIT_BREAKER_PERSIST_TO_REDIS:-true}
# Cache CACHE_ENABLED: ${CACHE_ENABLED:-true} CACHE_DEFAULT_TTL: ${CACHE_DEFAULT_TTL:-300} CACHE_STALE_TTL: ${CACHE_STALE_TTL:-7200}
# Metrics METRICS_ENABLED: ${METRICS_ENABLED:-true} METRICS_FLUSH_INTERVAL_MS: ${METRICS_FLUSH_INTERVAL_MS:-60000} LOG_LEVEL: ${LOG_LEVEL:-info}
# Health Check HEALTH_CHECK_PORT: 8000 HEALTH_CHECK_ENABLED: true env_file: - .env depends_on: postgres: condition: service_healthy redis: condition: service_healthy minio: condition: service_healthy restart: unless-stopped healthcheck: test: ['CMD-SHELL', 'wget --no-verbose --tries=1 --spider http://localhost:8000/health || exit 1'] interval: 30s timeout: 10s retries: 3 start_period: 40s
frontend: build: context: . dockerfile: apps/isekai-frontend/Dockerfile # No build args needed - config is injected at runtime ports: - '3000:80' # Map host 3000 to container 80 (nginx) environment: # Runtime environment variables (injected by entrypoint script) VITE_API_URL: ${VITE_API_URL:-http://localhost:4000/api} VITE_DEVIANTART_CLIENT_ID: ${DEVIANTART_CLIENT_ID} VITE_S3_PUBLIC_URL: ${S3_PUBLIC_URL:-http://localhost:9000/isekai-uploads} env_file: - .env depends_on: - backend restart: unless-stopped
volumes: postgres_data: redis_data: minio_data:Service Breakdown
Section titled “Service Breakdown”PostgreSQL (postgres)
Section titled “PostgreSQL (postgres)”- Image:
postgres:16-alpine - Purpose: Primary database for application data
- Volume:
postgres_data- Persists all user data, drafts, and schedules - Health Check: Verifies database is ready before starting dependent services
MinIO (minio)
Section titled “MinIO (minio)”- Image:
minio/minio:latest - Purpose: S3-compatible object storage for uploaded files
- Volume:
minio_data- Persists all uploaded images and files - Ports: 9000 (S3 API), 9001 (Web Console)
- Console: Access at http://localhost:9001 (login: minioadmin / minioadmin)
MinIO Init (minio-init)
Section titled “MinIO Init (minio-init)”- Image:
minio/mc:latest - Purpose: One-time initialization to create the default bucket
- Behavior: Creates
isekai-uploadsbucket and sets it to public download
Redis (redis)
Section titled “Redis (redis)”- Image:
redis:7-alpine - Purpose: Session storage, job queues, and caching
- Volume:
redis_data- Persists session data and queue jobs - Persistence: Configured with AOF (Append-Only File) for data durability
Backend (backend)
Section titled “Backend (backend)”- Image: Built from
apps/isekai-backend/Dockerfile - Purpose: API server, authentication, and job scheduling
- Dependencies: Waits for PostgreSQL, Redis, and MinIO to be healthy
- Port: 4000 (configurable via
BACKEND_PORT)
Publisher (publisher)
Section titled “Publisher (publisher)”- Image: Built from
apps/isekai-publisher/Dockerfile - Purpose: Background worker for publishing to DeviantArt
- Dependencies: Waits for PostgreSQL, Redis, and MinIO to be healthy
- Port: 8000 (health check endpoint)
Frontend (frontend)
Section titled “Frontend (frontend)”- Image: Built from
apps/isekai-frontend/Dockerfile - Purpose: User interface (React SPA)
- Dependencies: Backend API
- Port: 80 internally, mapped to 3000 externally (configurable via
FRONTEND_PORT)
Using External Storage
Section titled “Using External Storage”If you prefer to use an external S3-compatible storage provider (Cloudflare R2, AWS S3, etc.) instead of the included MinIO, simply override the S3_* environment variables in your .env file. See the Storage Setup guide for configuration details.