Skip to main content

Overview

ClassroomIO can be self-hosted using Docker containers. We provide pre-built Docker images for both the API and Dashboard services, making deployment straightforward and consistent across different environments.

Prerequisites

  • Docker (version 20.x or higher)
  • Docker Compose (version 2.x or higher)
  • At least 2GB of RAM
  • A Supabase instance (local or cloud)

Quick Start

Using Pre-built Images

The easiest way to get started is using our official Docker images from Docker Hub:
# Pull the latest images
docker pull classroomio/api:latest
docker pull classroomio/dashboard:latest

Docker Compose Setup

  1. Create a docker-compose.yaml file:
docker-compose.yaml
version: "3.8"

services:
  api:
    image: classroomio/api:latest
    ports:
      - "3081:3081"
    environment:
      - NODE_ENV=production
      # Supabase - Database
      - PUBLIC_SUPABASE_ANON_KEY=${PUBLIC_SUPABASE_ANON_KEY}
      - PUBLIC_SUPABASE_URL=${PUBLIC_SUPABASE_URL}
      # Cloudflare - Video upload
      - CLOUDFLARE_BUCKET_DOMAIN=${CLOUDFLARE_BUCKET_DOMAIN}
      - CLOUDFLARE_ACCESS_KEY=${CLOUDFLARE_ACCESS_KEY}
      - CLOUDFLARE_SECRET_ACCESS_KEY=${CLOUDFLARE_SECRET_ACCESS_KEY}
      - CLOUDFLARE_ACCOUNT_ID=${CLOUDFLARE_ACCOUNT_ID}
      # SMTP - Emails
      - SMTP_HOST=${SMTP_HOST}
      - SMTP_USER=${SMTP_USER}
      - SMTP_PASSWORD=${SMTP_PASSWORD}
      - SMTP_PORT=${SMTP_PORT}
      - SMTP_SENDER=${SMTP_SENDER}
      # Redis
      - REDIS_URL=${REDIS_URL}

  dashboard:
    image: classroomio/dashboard:latest
    ports:
      - "3082:3082"
    environment:
      - PUBLIC_IS_SELFHOSTED=true
      # Supabase - Database
      - PUBLIC_SUPABASE_URL=${PUBLIC_SUPABASE_URL}
      - PUBLIC_SUPABASE_ANON_KEY=${PUBLIC_SUPABASE_ANON_KEY}
      - PRIVATE_SUPABASE_SERVICE_ROLE=${PRIVATE_SUPABASE_SERVICE_ROLE}
      - PRIVATE_APP_HOST=${PRIVATE_APP_HOST}
      - PRIVATE_APP_SUBDOMAINS=${PRIVATE_APP_SUBDOMAINS}
      - UNSPLASH_API_KEY=${UNSPLASH_API_KEY}
      - OPENAI_API_KEY=${OPENAI_API_KEY}
      - PUBLIC_SERVER_URL=${PUBLIC_SERVER_URL}
      - PUBLIC_IP_REGISTRY_KEY=${PUBLIC_IP_REGISTRY_KEY}
    depends_on:
      - api
  1. Create a .env file with your configuration:
.env
# Supabase Configuration
PUBLIC_SUPABASE_URL=https://your-project.supabase.co
PUBLIC_SUPABASE_ANON_KEY=your-anon-key
PRIVATE_SUPABASE_SERVICE_ROLE=your-service-role-key

# Domain Configuration
PRIVATE_APP_HOST=yourdomain.com
PRIVATE_APP_SUBDOMAINS=app

# API URL
PUBLIC_SERVER_URL=http://localhost:3081
  1. Start the services:
docker-compose up -d
  1. Access your instance:
    • Dashboard: http://localhost:3082
    • API: http://localhost:3081

Building Custom Images

If you need to build images from source:

Build API Image

docker build -f docker/Dockerfile.api -t classroomio/api:latest .

Build Dashboard Image

docker build -f docker/Dockerfile.dashboard -t classroomio/dashboard:latest .

Container Details

API Container

  • Base Image: node:20.19.3-slim
  • Port: 3081
  • Working Directory: /app
  • Build Tool: pnpm + turbo
  • Size: ~400-600 MB

Dashboard Container

  • Base Image: node:20.19.3-alpine
  • Port: 3082
  • Working Directory: /app
  • Framework: SvelteKit
  • Size: ~600-800 MB
  • User: cio-user (non-root)

Docker Commands

View Logs

# All services
docker-compose logs -f

# Specific service
docker-compose logs -f api
docker-compose logs -f dashboard

Restart Services

# All services
docker-compose restart

# Specific service
docker-compose restart api

Stop Services

docker-compose down

Rebuild Services

docker-compose up -d --build

Check Running Containers

docker-compose ps

Production Deployment

Resource Requirements

  • CPU: 2+ cores recommended
  • RAM: 2GB minimum, 4GB recommended
  • Storage: 10GB minimum

Best Practices

  1. Use specific version tags instead of latest in production:
    image: classroomio/api:v1.0.0
    
  2. Enable health checks:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3081/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    
  3. Use environment-specific configurations:
    docker-compose -f docker-compose.prod.yaml up -d
    
  4. Set up logging:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    
  5. Use Docker secrets for sensitive data instead of environment variables

Troubleshooting

Port Conflicts

If ports 3081 or 3082 are already in use:
ports:
  - "8081:3081"  # Map to different host port

Container Won’t Start

  1. Check logs:
    docker-compose logs api
    
  2. Verify environment variables are set correctly
  3. Ensure Supabase is accessible

Build Failures

  1. Clear Docker cache:
    docker system prune -a
    
  2. Rebuild without cache:
    docker-compose build --no-cache
    

Memory Issues

Increase Docker memory allocation in Docker Desktop settings or add resource limits:
services:
  api:
    deploy:
      resources:
        limits:
          memory: 1G

Multi-Architecture Support

Our Docker images support both:
  • linux/amd64 (x86_64 servers)
  • linux/arm64 (ARM servers, Apple Silicon)

Next Steps

Environment Variables

Configure all required environment variables

Supabase Setup

Set up your Supabase database

Custom Domain

Configure custom domains

Build docs developers (and LLMs) love