From ce73f89da22e3b43f7a7655bfbf1b1cc08559251 Mon Sep 17 00:00:00 2001 From: Christian Krakau-Louis Date: Mon, 7 Apr 2025 00:43:14 +0200 Subject: [PATCH] feat: Enhance Docker setup and application status reporting with build date and container info --- Dockerfile | 31 +++++------ app/views/general.py | 20 +++++-- app/views/status.py | 68 +++++++++++++++++++++++- docker-compose.yaml | 5 +- docker/build-scripts/save-build-date.sh | 11 ---- frontend/templates/status_dashboard.html | 10 ++++ 6 files changed, 109 insertions(+), 36 deletions(-) delete mode 100644 docker/build-scripts/save-build-date.sh diff --git a/Dockerfile b/Dockerfile index 9f58d8f6..d16c09a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,41 +1,38 @@ -# Stage 1: Build dependencies +# Use multi-stage build for a smaller final image FROM python:3.13 AS builder WORKDIR /app +# Copy requirements first for better layer caching COPY requirements.txt /app/ RUN pip install --no-cache-dir -r requirements.txt -# Stage 2: Final image +# Second stage for the actual runtime FROM python:3.13.2-slim WORKDIR /app -# Copy installed dependencies +# Copy installed packages from builder stage COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages COPY --from=builder /usr/local/bin /usr/local/bin -# Copy application files correctly +# Copy application code COPY ./app /app/app -COPY ./frontend /app/frontend COPY ./VERSION /app/VERSION -COPY ./LICENSE /app/LICENSE +COPY ./frontend /app/frontend -# Copy build script and generate build date -COPY ./docker/build-scripts/save-build-date.sh /tmp/ -RUN mkdir -p /app/docker/build-scripts/ && \ - cp /tmp/save-build-date.sh /app/docker/build-scripts/ && \ - chmod +x /tmp/save-build-date.sh && \ - /tmp/save-build-date.sh +# Create runtime_info directory +RUN mkdir -p /app/runtime_info -# Set build date as environment variable -#ENV BUILD_DATE=$(cat /app/BUILD_DATE) +# Create necessary directories +RUN mkdir -p /workdir -# Set Python path explicitly +# Set environment variables ENV PYTHONPATH=/app +ENV PYTHONUNBUFFERED=1 -# Expose API port +# Expose the port the app runs on EXPOSE 8000 -WORKDIR /app +# Default command CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/app/views/general.py b/app/views/general.py index ed51af7d..5b010a3f 100644 --- a/app/views/general.py +++ b/app/views/general.py @@ -1,18 +1,19 @@ """ General routes for the application homepage and basic pages. """ -from fastapi import Request, HTTPException +from fastapi import Request, HTTPException, Depends from fastapi.responses import FileResponse from pathlib import Path from datetime import date +from sqlalchemy.orm import Session -from app.views.base import APIRouter, templates, require_login +from app.views.base import APIRouter, templates, require_login, get_db from app.utils.config_validator import get_provider_status, validate_storage_configs router = APIRouter() @router.get("/", include_in_schema=False) -async def serve_index(request: Request): +async def serve_index(request: Request, db: Session = Depends(get_db)): """Serve the index/home page.""" # Get provider information from config validator providers = get_provider_status() @@ -27,9 +28,20 @@ async def serve_index(request: Request): 's3', 'ftp', 'webdav', 'google_drive', 'onedrive']) + # Query the actual file count from the database + processed_files = 0 + try: + # Import the model here to avoid circular imports + from app.models import FileRecord + processed_files = db.query(FileRecord).count() + except Exception as e: + # Log error but continue (don't break the page if DB query fails) + from app.views.base import logger + logger.error(f"Error counting files: {str(e)}") + # Create stats object to pass to the template stats = { - "processed_files": 0, # Placeholder - would need actual DB query + "processed_files": processed_files, "active_integrations": configured_providers, "storage_targets": configured_storage_targets } diff --git a/app/views/status.py b/app/views/status.py index a1a93cc9..a7297d34 100644 --- a/app/views/status.py +++ b/app/views/status.py @@ -3,6 +3,8 @@ Status and configuration views for the application. """ from fastapi import Request from datetime import datetime +import os +import subprocess from app.views.base import APIRouter, templates, require_login, settings @@ -19,14 +21,78 @@ async def status_dashboard(request: Request): # Get provider status providers = get_provider_status() + # Get build date from settings + build_date = getattr(settings, 'build_date', 'Unknown') + + # Try to get container information + container_info = {} + try: + # Check for Docker environment + if os.path.exists('/.dockerenv'): + # We're inside a Docker container + container_info['is_docker'] = True + + # Try to get container ID + try: + with open('/proc/self/cgroup', 'r') as f: + for line in f: + if 'docker' in line: + container_id = line.split('/')[-1].strip() + container_info['id'] = container_id[:12] # Short ID format + break + except Exception: + container_info['id'] = 'Unknown' + + # Try to get Git commit SHA from runtime info + try: + # First check runtime info directory + if os.path.exists('/app/runtime_info/GIT_SHA'): + with open('/app/runtime_info/GIT_SHA', 'r') as f: + git_sha = f.read().strip() + # Then try environment variable + else: + git_sha = os.environ.get('GIT_COMMIT_SHA', '') + + # If still not found, try the original file location + if not git_sha and os.path.exists('/.git-commit-sha'): + with open('/.git-commit-sha', 'r') as f: + git_sha = f.read().strip() + + container_info['git_sha'] = git_sha[:7] if git_sha and git_sha != 'unknown' else 'Unknown' + except Exception: + container_info['git_sha'] = 'Unknown' + + # Try to get runtime information + try: + if os.path.exists('/app/runtime_info/RUNTIME_INFO'): + with open('/app/runtime_info/RUNTIME_INFO', 'r') as f: + container_info['runtime_info'] = f.read().strip() + except Exception: + pass + else: + container_info['is_docker'] = False + + # If not in Docker, try to get Git info directly + try: + git_sha = subprocess.check_output(['git', 'rev-parse', 'HEAD'], + stderr=subprocess.DEVNULL, + text=True).strip()[:7] + container_info['git_sha'] = git_sha + except (subprocess.SubprocessError, FileNotFoundError): + container_info['git_sha'] = 'Unknown' + except Exception: + container_info = {'is_docker': False, 'id': 'Unknown', 'git_sha': 'Unknown'} + return templates.TemplateResponse( "status_dashboard.html", { "request": request, "providers": providers, "app_version": settings.version, + "build_date": build_date, "debug_enabled": getattr(settings, 'debug', False), - "last_check": datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "last_check": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + "container_info": container_info } ) diff --git a/docker-compose.yaml b/docker-compose.yaml index d7faf546..e09c5b23 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -10,7 +10,7 @@ services: working_dir: /workdir # We'll run uvicorn from the container's /app code - command: ["sh", "-c", "cd /app && uvicorn app.main:app --host 0.0.0.0 --port 8000 --proxy-headers"] + command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--proxy-headers"] # Environment variables environment: @@ -50,7 +50,7 @@ services: - redis - gotenberg - # Mount the shared directory (and optionally your code if you want dev mode) + # Mount the shared directory volumes: - /var/docparse/workdir:/workdir @@ -59,7 +59,6 @@ services: container_name: gotenberg restart: always - redis: image: redis:alpine container_name: document_redis diff --git a/docker/build-scripts/save-build-date.sh b/docker/build-scripts/save-build-date.sh deleted file mode 100644 index 3a459f50..00000000 --- a/docker/build-scripts/save-build-date.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -# Get current date in Month DD, YYYY format (e.g., May 15, 2024) -BUILD_DATE=$(date +"%B %d, %Y") - -# Save it to the BUILD_DATE file -echo $BUILD_DATE > /app/BUILD_DATE - -# Also set it as an environment variable -echo "Setting BUILD_DATE=$BUILD_DATE" -export BUILD_DATE diff --git a/frontend/templates/status_dashboard.html b/frontend/templates/status_dashboard.html index 7ebdc987..66baea96 100644 --- a/frontend/templates/status_dashboard.html +++ b/frontend/templates/status_dashboard.html @@ -14,10 +14,20 @@