feat: Enhance Docker setup and application status reporting with build date and container info

This commit is contained in:
Christian Krakau-Louis
2025-04-07 00:43:14 +02:00
parent c7ddf77cb2
commit d66fef7ad4
6 changed files with 109 additions and 36 deletions
+14 -17
View File
@@ -1,41 +1,38 @@
# Stage 1: Build dependencies # Use multi-stage build for a smaller final image
FROM python:3.13 AS builder FROM python:3.13 AS builder
WORKDIR /app WORKDIR /app
# Copy requirements first for better layer caching
COPY requirements.txt /app/ COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt 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 FROM python:3.13.2-slim
WORKDIR /app 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/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin COPY --from=builder /usr/local/bin /usr/local/bin
# Copy application files correctly # Copy application code
COPY ./app /app/app COPY ./app /app/app
COPY ./frontend /app/frontend
COPY ./VERSION /app/VERSION COPY ./VERSION /app/VERSION
COPY ./LICENSE /app/LICENSE COPY ./frontend /app/frontend
# Copy build script and generate build date # Create runtime_info directory
COPY ./docker/build-scripts/save-build-date.sh /tmp/ RUN mkdir -p /app/runtime_info
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
# Set build date as environment variable # Create necessary directories
#ENV BUILD_DATE=$(cat /app/BUILD_DATE) RUN mkdir -p /workdir
# Set Python path explicitly # Set environment variables
ENV PYTHONPATH=/app ENV PYTHONPATH=/app
ENV PYTHONUNBUFFERED=1
# Expose API port # Expose the port the app runs on
EXPOSE 8000 EXPOSE 8000
WORKDIR /app
# Default command
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
+16 -4
View File
@@ -1,18 +1,19 @@
""" """
General routes for the application homepage and basic pages. 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 fastapi.responses import FileResponse
from pathlib import Path from pathlib import Path
from datetime import date 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 from app.utils.config_validator import get_provider_status, validate_storage_configs
router = APIRouter() router = APIRouter()
@router.get("/", include_in_schema=False) @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.""" """Serve the index/home page."""
# Get provider information from config validator # Get provider information from config validator
providers = get_provider_status() providers = get_provider_status()
@@ -27,9 +28,20 @@ async def serve_index(request: Request):
's3', 'ftp', 'webdav', 's3', 'ftp', 'webdav',
'google_drive', 'onedrive']) '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 # Create stats object to pass to the template
stats = { stats = {
"processed_files": 0, # Placeholder - would need actual DB query "processed_files": processed_files,
"active_integrations": configured_providers, "active_integrations": configured_providers,
"storage_targets": configured_storage_targets "storage_targets": configured_storage_targets
} }
+67 -1
View File
@@ -3,6 +3,8 @@ Status and configuration views for the application.
""" """
from fastapi import Request from fastapi import Request
from datetime import datetime from datetime import datetime
import os
import subprocess
from app.views.base import APIRouter, templates, require_login, settings from app.views.base import APIRouter, templates, require_login, settings
@@ -19,14 +21,78 @@ async def status_dashboard(request: Request):
# Get provider status # Get provider status
providers = 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( return templates.TemplateResponse(
"status_dashboard.html", "status_dashboard.html",
{ {
"request": request, "request": request,
"providers": providers, "providers": providers,
"app_version": settings.version, "app_version": settings.version,
"build_date": build_date,
"debug_enabled": getattr(settings, 'debug', False), "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
} }
) )
+2 -3
View File
@@ -10,7 +10,7 @@ services:
working_dir: /workdir working_dir: /workdir
# We'll run uvicorn from the container's /app code # 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 variables
environment: environment:
@@ -50,7 +50,7 @@ services:
- redis - redis
- gotenberg - gotenberg
# Mount the shared directory (and optionally your code if you want dev mode) # Mount the shared directory
volumes: volumes:
- /var/docparse/workdir:/workdir - /var/docparse/workdir:/workdir
@@ -59,7 +59,6 @@ services:
container_name: gotenberg container_name: gotenberg
restart: always restart: always
redis: redis:
image: redis:alpine image: redis:alpine
container_name: document_redis container_name: document_redis
-11
View File
@@ -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
+10
View File
@@ -14,10 +14,20 @@
</p> </p>
<div class="bg-blue-100 border-l-4 border-blue-500 text-blue-700 p-4 my-4" role="alert"> <div class="bg-blue-100 border-l-4 border-blue-500 text-blue-700 p-4 my-4" role="alert">
<p><strong>App Version:</strong> {{ app_version }}</p> <p><strong>App Version:</strong> {{ app_version }}</p>
<p><strong>Build Date:</strong> {{ build_date }}</p>
<p><strong>Debug Mode:</strong> {{ "Enabled" if debug_enabled else "Disabled" }}</p> <p><strong>Debug Mode:</strong> {{ "Enabled" if debug_enabled else "Disabled" }}</p>
{% if last_check %} {% if last_check %}
<p><strong>Last Check:</strong> {{ last_check }}</p> <p><strong>Last Check:</strong> {{ last_check }}</p>
{% endif %} {% endif %}
{% if container_info.is_docker %}
<p><strong>Container ID:</strong> {{ container_info.id }}</p>
{% endif %}
{% if container_info.git_sha and container_info.git_sha != 'Unknown' %}
<p><strong>Git Commit:</strong> {{ container_info.git_sha }}</p>
{% endif %}
{% if container_info.runtime_info %}
<p><strong>Container Started:</strong> {{ container_info.runtime_info }}</p>
{% endif %}
</div> </div>
</div> </div>