From 68942410ae9a599cea18d2e0a2cc1be12bb73719 Mon Sep 17 00:00:00 2001 From: "IGNY8 VPS (Salman)" Date: Mon, 15 Dec 2025 07:14:06 +0000 Subject: [PATCH] only restart issue and logout issue debugging added --- CONTAINER-RESTART-DEBUGGING.md | 174 ++++++++++++++++++++++++++ backend/Dockerfile | 6 + backend/container_startup.sh | 47 +++++++ backend/igny8_core/auth/middleware.py | 23 +++- backend/igny8_core/settings.py | 10 ++ frontend/Dockerfile.dev | 6 + frontend/container_startup.sh | 44 +++++++ frontend/vite.config.ts | 9 ++ 8 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 CONTAINER-RESTART-DEBUGGING.md create mode 100644 backend/container_startup.sh create mode 100644 frontend/container_startup.sh diff --git a/CONTAINER-RESTART-DEBUGGING.md b/CONTAINER-RESTART-DEBUGGING.md new file mode 100644 index 00000000..7c0e3662 --- /dev/null +++ b/CONTAINER-RESTART-DEBUGGING.md @@ -0,0 +1,174 @@ +# Container Restart and Auto-Logout Debugging Setup + +## Overview +Added comprehensive logging to track container restarts and automatic user logouts. + +## Changes Made + +### 1. Container Lifecycle Logging + +#### Backend Container (`backend/container_startup.sh`) +- Logs container startup time, hostname, and PID +- Detects and logs container restarts (by checking for previous PID file) +- Logs environment configuration (Python version, Django settings, DB host) +- Warns when restarts are detected and suggests checking Docker logs for SIGTERM signals +- Integrated into Dockerfile as ENTRYPOINT + +#### Frontend Container (`frontend/container_startup.sh`) +- Logs container startup time, hostname, and PID +- Detects and logs container restarts +- Logs Node/NPM versions and Vite configuration +- Checks for git directory presence and warns about file watching +- Shows last git commit when detected +- Integrated into Dockerfile.dev as ENTRYPOINT + +### 2. Vite File Watching Fix (`frontend/vite.config.ts`) + +**ROOT CAUSE IDENTIFIED:** `usePolling: true` was watching ALL files including `.git` directory, causing container restarts on git commits. + +**Fix Applied:** +```typescript +watch: { + usePolling: true, + ignored: [ + '**/node_modules/**', + '**/.git/**', // CRITICAL: Ignore git directory + '**/dist/**', + '**/build/**', + '**/.vscode/**', + '**/.idea/**', + ], + interval: 1000, // Poll every 1 second instead of default +} +``` + +### 3. Auto-Logout Logging (`backend/igny8_core/auth/middleware.py`) + +Added detailed logging for all automatic logout scenarios: + +#### Session Contamination - Account ID Mismatch +```python +logger.warning( + f"[AUTO-LOGOUT] Session contamination: account_id mismatch. " + f"Session={stored_account_id}, Current={request.account.id}, " + f"User={request.user.id}, Path={request.path}, IP={request.META.get('REMOTE_ADDR')}" +) +``` + +#### Session Contamination - User ID Mismatch +```python +logger.warning( + f"[AUTO-LOGOUT] Session contamination: user_id mismatch. " + f"Session={stored_user_id}, Current={request.user.id}, " + f"Account={request.account.id if request.account else None}, " + f"Path={request.path}, IP={request.META.get('REMOTE_ADDR')}" +) +``` + +#### Account/Plan Validation Failures +```python +logger.warning( + f"[AUTO-LOGOUT] Account/plan validation failed: {error}. " + f"User={request.user.id}, Account={getattr(request, 'account', None)}, " + f"Path={request.path}, IP={request.META.get('REMOTE_ADDR')}" +) +``` + +### 4. Logging Configuration (`backend/igny8_core/settings.py`) + +Added two new loggers: +- `auth.middleware` - Captures all authentication and auto-logout events +- `container.lifecycle` - Captures container startup/restart events + +Both log to console (captured by Docker logs). + +## How to Use + +### Viewing Container Restart Logs + +```bash +# Check backend container logs for restart events +docker logs igny8_backend 2>&1 | grep "CONTAINER-STARTUP\|RESTART" + +# Check frontend container logs for restart events +docker logs igny8_frontend 2>&1 | grep "CONTAINER-STARTUP\|RESTART" + +# Monitor in real-time +docker logs -f igny8_backend +``` + +### Viewing Auto-Logout Logs + +```bash +# Check for automatic logout events +docker logs igny8_backend 2>&1 | grep "AUTO-LOGOUT" + +# Filter by specific logout reason +docker logs igny8_backend 2>&1 | grep "AUTO-LOGOUT.*contamination" +docker logs igny8_backend 2>&1 | grep "AUTO-LOGOUT.*validation failed" + +# See recent logout events with context +docker logs --since 1h igny8_backend 2>&1 | grep -A2 -B2 "AUTO-LOGOUT" +``` + +### Correlating Events + +```bash +# See both container restarts and logouts together +docker logs --since 2h igny8_backend 2>&1 | grep -E "CONTAINER-STARTUP|AUTO-LOGOUT|SIGTERM" + +# Check if git commits correlate with restarts +git log --since="2 hours ago" --format="%ai %s" && \ +docker logs --since 2h igny8_frontend 2>&1 | grep "CONTAINER-STARTUP" +``` + +## Next Steps to Deploy + +1. **Rebuild Docker images:** + ```bash + cd /data/app/igny8/backend + docker build -t igny8-backend:latest -f Dockerfile . + + cd /data/app/igny8/frontend + docker build -t igny8-frontend-dev:latest -f Dockerfile.dev . + ``` + +2. **Restart containers:** + ```bash + cd /data/app/igny8 + docker compose -f docker-compose.app.yml down + docker compose -f docker-compose.app.yml up -d + ``` + +3. **Verify logging is working:** + ```bash + docker logs igny8_backend 2>&1 | head -30 + docker logs igny8_frontend 2>&1 | head -30 + ``` + +4. **Test git commit trigger (should NOT restart now):** + ```bash + cd /data/app/igny8 + echo "test" >> README.md + git add README.md + git commit -m "test commit" + + # Wait 5 seconds and check - containers should NOT restart + sleep 5 + docker ps --filter "name=igny8" --format "{{.Names}}: {{.Status}}" + ``` + +## Expected Outcomes + +1. **Git commits should NO LONGER trigger container restarts** because `.git` is now ignored by Vite's file watcher +2. **Every container restart will be logged** with timestamp and reason +3. **Every automatic logout will be logged** with user ID, account ID, reason, path, and IP address +4. **You can correlate restarts with git operations** to verify the fix is working + +## Troubleshooting + +If containers still restart after git commits: +1. Check if the new images were built and deployed +2. Verify the vite.config.ts changes are present in the running container +3. Check Docker logs to see what triggered the restart +4. Look for HMR messages in frontend logs mentioning `.git` files diff --git a/backend/Dockerfile b/backend/Dockerfile index cb01f7ae..e38ee575 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -22,6 +22,10 @@ RUN pip install --upgrade pip \ # Copy full project COPY . /app/ +# Copy startup script +COPY container_startup.sh /app/ +RUN chmod +x /app/container_startup.sh + # Collect static files for WhiteNoise (skip during build if DB not available) # Will be run during container startup if needed RUN python manage.py collectstatic --noinput || echo "Skipping collectstatic during build" @@ -32,5 +36,7 @@ ENV DJANGO_SETTINGS_MODULE=igny8_core.settings # Expose port for Gunicorn (matches Portainer docker-compose config) EXPOSE 8010 +# Use startup script as entrypoint to log container lifecycle # Start using Gunicorn (matches Portainer docker-compose config) +ENTRYPOINT ["/app/container_startup.sh"] CMD ["gunicorn", "igny8_core.wsgi:application", "--bind", "0.0.0.0:8010"] diff --git a/backend/container_startup.sh b/backend/container_startup.sh new file mode 100644 index 00000000..e0817164 --- /dev/null +++ b/backend/container_startup.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Container Startup Logger +# Logs container lifecycle events for debugging restarts + +set -e + +echo "==========================================" +echo "[CONTAINER-STARTUP] $(date '+%Y-%m-%d %H:%M:%S')" +echo "Container: igny8_backend" +echo "Hostname: $(hostname)" +echo "PID: $$" +echo "==========================================" + +# Log environment info +echo "[INFO] Python version: $(python --version 2>&1)" +echo "[INFO] Django settings: ${DJANGO_SETTINGS_MODULE:-igny8_core.settings}" +echo "[INFO] Debug mode: ${DEBUG:-False}" +echo "[INFO] Database host: ${DB_HOST:-not set}" + +# Check if this is a restart (look for previous process artifacts) +if [ -f /tmp/container_pid ]; then + PREV_PID=$(cat /tmp/container_pid) + echo "[WARNING] Previous container PID found: $PREV_PID" + echo "[WARNING] This appears to be a RESTART event" + echo "[WARNING] Check Docker logs for SIGTERM/SIGKILL signals" +else + echo "[INFO] First startup (no previous PID file found)" +fi + +# Save current PID +echo $$ > /tmp/container_pid + +# Run database migrations (will skip if up to date) +echo "[INFO] Running database migrations..." +python manage.py migrate --noinput || echo "[WARNING] Migration failed or skipped" + +# Collect static files (skip if already done) +echo "[INFO] Collecting static files..." +python manage.py collectstatic --noinput || echo "[WARNING] Collectstatic failed or skipped" + +echo "==========================================" +echo "[CONTAINER-STARTUP] Initialization complete" +echo "[CONTAINER-STARTUP] Starting Gunicorn..." +echo "==========================================" + +# Execute the CMD passed to the script (Gunicorn command) +exec "$@" diff --git a/backend/igny8_core/auth/middleware.py b/backend/igny8_core/auth/middleware.py index 94191d61..eb473faa 100644 --- a/backend/igny8_core/auth/middleware.py +++ b/backend/igny8_core/auth/middleware.py @@ -2,11 +2,14 @@ Multi-Account Middleware Extracts account from JWT token and injects into request context """ +import logging from django.utils.deprecation import MiddlewareMixin from django.http import JsonResponse from django.contrib.auth import logout from rest_framework import status +logger = logging.getLogger('auth.middleware') + try: import jwt JWT_AVAILABLE = True @@ -54,6 +57,11 @@ class AccountContextMiddleware(MiddlewareMixin): stored_user_id = request.session.get('_user_id') if stored_account_id and stored_account_id != request.account.id: # Session contamination detected - force logout + logger.warning( + f"[AUTO-LOGOUT] Session contamination: account_id mismatch. " + f"Session={stored_account_id}, Current={request.account.id}, " + f"User={request.user.id}, Path={request.path}, IP={request.META.get('REMOTE_ADDR')}" + ) logout(request) return JsonResponse( {'success': False, 'error': 'Session integrity violation detected. Please login again.'}, @@ -61,6 +69,12 @@ class AccountContextMiddleware(MiddlewareMixin): ) if stored_user_id and stored_user_id != request.user.id: # Session contamination detected - force logout + logger.warning( + f"[AUTO-LOGOUT] Session contamination: user_id mismatch. " + f"Session={stored_user_id}, Current={request.user.id}, " + f"Account={request.account.id if request.account else None}, " + f"Path={request.path}, IP={request.META.get('REMOTE_ADDR')}" + ) logout(request) return JsonResponse( {'success': False, 'error': 'Session integrity violation detected. Please login again.'}, @@ -173,9 +187,14 @@ class AccountContextMiddleware(MiddlewareMixin): """Logout session users (if any) and return a consistent JSON error.""" try: if hasattr(request, 'user') and request.user and request.user.is_authenticated: + logger.warning( + f"[AUTO-LOGOUT] Account/plan validation failed: {error}. " + f"User={request.user.id}, Account={getattr(request, 'account', None)}, " + f"Path={request.path}, IP={request.META.get('REMOTE_ADDR')}" + ) logout(request) - except Exception: - pass + except Exception as e: + logger.error(f"[AUTO-LOGOUT] Error during logout: {e}") return JsonResponse( { diff --git a/backend/igny8_core/settings.py b/backend/igny8_core/settings.py index 2af4514c..52209c61 100644 --- a/backend/igny8_core/settings.py +++ b/backend/igny8_core/settings.py @@ -604,6 +604,16 @@ LOGGING = { 'level': 'INFO', 'propagate': False, }, + 'auth.middleware': { + 'handlers': ['console'], + 'level': 'INFO', + 'propagate': False, + }, + 'container.lifecycle': { + 'handlers': ['console'], + 'level': 'INFO', + 'propagate': False, + }, }, } diff --git a/frontend/Dockerfile.dev b/frontend/Dockerfile.dev index d60507b2..345edc5a 100644 --- a/frontend/Dockerfile.dev +++ b/frontend/Dockerfile.dev @@ -12,9 +12,15 @@ RUN npm install # Copy source code (will be mounted as volume, but needed for initial setup) COPY . . +# Copy startup script +COPY container_startup.sh /app/ +RUN chmod +x /app/container_startup.sh + # Expose Vite dev server port EXPOSE 5173 +# Use startup script as entrypoint to log container lifecycle # Start Vite dev server with host binding for Docker +ENTRYPOINT ["/app/container_startup.sh"] CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0", "--port", "5173"] diff --git a/frontend/container_startup.sh b/frontend/container_startup.sh new file mode 100644 index 00000000..a5ae338c --- /dev/null +++ b/frontend/container_startup.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# Frontend Container Startup Logger +# Logs container lifecycle events for debugging restarts + +echo "==========================================" +echo "[CONTAINER-STARTUP] $(date '+%Y-%m-%d %H:%M:%S')" +echo "Container: igny8_frontend" +echo "Hostname: $(hostname)" +echo "PID: $$" +echo "==========================================" + +# Log environment info +echo "[INFO] Node version: $(node --version 2>&1)" +echo "[INFO] NPM version: $(npm --version 2>&1)" +echo "[INFO] Vite backend URL: ${VITE_BACKEND_URL:-not set}" +echo "[INFO] Working directory: $(pwd)" + +# Check if this is a restart +if [ -f /tmp/container_pid ]; then + PREV_PID=$(cat /tmp/container_pid) + echo "[WARNING] Previous container PID found: $PREV_PID" + echo "[WARNING] This appears to be a RESTART event" + echo "[WARNING] Check Docker logs for SIGTERM/SIGKILL signals" +else + echo "[INFO] First startup (no previous PID file found)" +fi + +# Save current PID +echo $$ > /tmp/container_pid + +# Check for git directory changes (common restart trigger) +if [ -d "/app/.git" ]; then + echo "[INFO] Git directory detected in /app/.git" + echo "[WARNING] Git operations may trigger container restarts due to Vite file watching" + echo "[INFO] Last git commit: $(cd /app && git log -1 --format='%h %s' 2>/dev/null || echo 'N/A')" +fi + +echo "==========================================" +echo "[CONTAINER-STARTUP] Initialization complete" +echo "[CONTAINER-STARTUP] Starting Vite dev server..." +echo "==========================================" + +# Execute the CMD passed to the script +exec "$@" diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 29bfacb2..e6964cf7 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -190,6 +190,15 @@ export default defineConfig(({ mode, command }) => { allowedHosts: true, watch: { usePolling: true, // Needed for file watching in Docker + ignored: [ + '**/node_modules/**', + '**/.git/**', // CRITICAL: Ignore git directory to prevent restart on commits + '**/dist/**', + '**/build/**', + '**/.vscode/**', + '**/.idea/**', + ], + interval: 1000, // Poll every 1 second (default is 100ms) }, hmr: { // Behind reverse proxy - explicitly set host and port to public domain