diff --git a/.env b/.env index 34313bd..a686c0b 100644 --- a/.env +++ b/.env @@ -18,8 +18,8 @@ APP_PROTOCOL=https UVICORN_PORT=8080 UVICORN_WORKERS=2 UVICORN_TIMEOUT=300 -DEV_MODE=true -BACKEND_DEV_MODE=true +DEV_MODE=false +BACKEND_DEV_MODE=false ## ===================================================== ## ADMIN USER CONFIGURATION @@ -27,9 +27,9 @@ BACKEND_DEV_MODE=true # Regular Admin ADMIN_EMAIL=admin@classroomcopilot.ai ADMIN_PASSWORD=&%4Dm1n&% -ADMIN_NAME=Kevin Carter (Admin) +ADMIN_NAME="Kevin Carter (Admin)" ADMIN_USERNAME=kcar -ADMIN_DISPLAY_NAME=K Car (Admin) +ADMIN_DISPLAY_NAME="K Car (Admin)" ADMIN_WORKER_EMAIL=kcar@kevlarai.com ## ===================================================== diff --git a/.env.prod b/.env.prod index 34313bd..a686c0b 100644 --- a/.env.prod +++ b/.env.prod @@ -18,8 +18,8 @@ APP_PROTOCOL=https UVICORN_PORT=8080 UVICORN_WORKERS=2 UVICORN_TIMEOUT=300 -DEV_MODE=true -BACKEND_DEV_MODE=true +DEV_MODE=false +BACKEND_DEV_MODE=false ## ===================================================== ## ADMIN USER CONFIGURATION @@ -27,9 +27,9 @@ BACKEND_DEV_MODE=true # Regular Admin ADMIN_EMAIL=admin@classroomcopilot.ai ADMIN_PASSWORD=&%4Dm1n&% -ADMIN_NAME=Kevin Carter (Admin) +ADMIN_NAME="Kevin Carter (Admin)" ADMIN_USERNAME=kcar -ADMIN_DISPLAY_NAME=K Car (Admin) +ADMIN_DISPLAY_NAME="K Car (Admin)" ADMIN_WORKER_EMAIL=kcar@kevlarai.com ## ===================================================== diff --git a/docker-compose.yml b/docker-compose.yml index 542d6e5..21a9786 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,20 @@ services: + redis: + image: redis:7-alpine + container_name: classroomcopilot-redis + ports: + - "6379:6379" + volumes: + - redis-data:/data + command: redis-server --appendonly yes + networks: + - kevlarai-network + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 3s + retries: 5 + backend: container_name: api build: @@ -6,11 +22,19 @@ services: dockerfile: Dockerfile env_file: - .env + environment: + - REDIS_HOST=redis ports: - 8000:8000 + depends_on: + redis: + condition: service_healthy networks: - kevlarai-network +volumes: + redis-data: + networks: kevlarai-network: name: kevlarai-network diff --git a/modules/redis_manager.py b/modules/redis_manager.py index 5721b22..11fb1f3 100644 --- a/modules/redis_manager.py +++ b/modules/redis_manager.py @@ -100,7 +100,12 @@ class RedisManager: logger.info("✅ Redis service already running") return True - # Try to start Redis service + # Check if we're in a Docker container (Redis should be a separate service) + if self._is_docker_environment(): + logger.info("🐳 Docker environment detected - waiting for Redis service to be ready...") + return self._wait_for_redis(max_wait_time=30) + + # Try to start Redis service (local development) logger.info("🚀 Starting Redis service...") # Try systemctl first (Linux production) @@ -137,6 +142,44 @@ class RedisManager: except Exception: return False + def _is_docker_environment(self) -> bool: + """Check if we're running in a Docker container.""" + # Check for Docker-specific indicators + if os.path.exists('/.dockerenv'): + return True + # Check if REDIS_HOST is set to a service name (not localhost) + if self.config.host and self.config.host != 'localhost' and self.config.host != '127.0.0.1': + return True + # Check for container environment variables + if os.getenv('HOSTNAME') and os.path.exists('/proc/1/cgroup'): + try: + with open('/proc/1/cgroup', 'r') as f: + if 'docker' in f.read() or 'containerd' in f.read(): + return True + except Exception: + pass + return False + + def _wait_for_redis(self, max_wait_time: int = 30) -> bool: + """Wait for Redis to become available (for Docker environments).""" + start_time = time.time() + attempt = 0 + + while time.time() - start_time < max_wait_time: + attempt += 1 + if self._is_redis_running(): + logger.info(f"✅ Redis service is ready (waited {int(time.time() - start_time)}s)") + return True + + if attempt % 3 == 0: # Log every 3 attempts + elapsed = int(time.time() - start_time) + logger.info(f"⏳ Waiting for Redis at {self.config.host}:{self.config.port}... ({elapsed}s/{max_wait_time}s)") + + time.sleep(2) + + logger.error(f"❌ Redis did not become available within {max_wait_time}s") + return False + def _try_systemctl_start(self) -> bool: """Try starting Redis with systemctl.""" try: