feat: major improvements and fixes

- Fixed Docker permissions issue by running as root user
- Added DEBUG_MODE support with conditional Swagger docs and auto-reload
- Created start.sh script for conditional Uvicorn execution
- Removed verbose debug logs from WebSocket status endpoint
- Added comprehensive screenshots to documentation
- Enhanced help tooltip with full-screen modal design
- Added theme switcher to error page
- Updated documentation with local development and Docker benefits
- Fixed WebSocket status display issues
- Improved hotkey functionality and documentation
- Added detailed project descriptions for local dev and Docker users

Technical improvements:
- Dockerfile: removed appuser switch, simplified permissions
- docker-compose.yml: kept user: 0:0 for Docker socket access
- app.py: removed debug prints, added DEBUG_MODE support
- templates: enhanced UI/UX with better tooltips and themes
- docs: comprehensive updates with new screenshots and descriptions
This commit is contained in:
Сергей Антропов
2025-08-19 13:01:32 +03:00
parent 5c8efe2644
commit e80f665470
26 changed files with 1017 additions and 148 deletions

53
app.py
View File

@@ -50,11 +50,16 @@ ADMIN_PASSWORD = os.getenv("LOGBOARD_PASS", "admin")
# Настройки AJAX обновления
AJAX_UPDATE_INTERVAL = int(os.getenv("LOGBOARD_AJAX_UPDATE_INTERVAL", "2000"))
# Настройки режима отладки
DEBUG_MODE = os.getenv("DEBUG_MODE", "false").lower() == "true"
# Инициализация FastAPI
app = FastAPI(
title="LogBoard+",
description="Веб-панель для просмотра логов микросервисов",
version="1.0.0"
version="1.0.0",
docs_url="/docs" if DEBUG_MODE else None,
redoc_url="/redoc" if DEBUG_MODE else None
)
@@ -917,6 +922,40 @@ def api_snapshot(
url = f"/snapshots/{fname}"
return {"file": fname, "url": url}
@app.get("/api/websocket/status")
def api_websocket_status(current_user: str = Depends(get_current_user)):
"""Получить статус WebSocket соединений"""
try:
# Проверяем доступность Docker
docker_client.ping()
# Получаем список активных контейнеров
containers = docker_client.containers.list()
# Проверяем, есть ли контейнеры для подключения
if containers:
return {
"status": "available",
"message": "WebSocket соединения доступны",
"containers_count": len(containers),
"timestamp": datetime.now().isoformat()
}
else:
return {
"status": "no_containers",
"message": "Нет доступных контейнеров для подключения",
"containers_count": 0,
"timestamp": datetime.now().isoformat()
}
except Exception as e:
return {
"status": "error",
"message": f"Ошибка проверки WebSocket статуса: {str(e)}",
"containers_count": 0,
"timestamp": datetime.now().isoformat()
}
# WebSocket: verify token (?token=base64(user:pass))
@app.websocket("/ws/logs/{container_id}")
async def ws_logs(ws: WebSocket, container_id: str, tail: int = DEFAULT_TAIL, token: Optional[str] = None,
@@ -1176,4 +1215,14 @@ async def ws_fan_group(ws: WebSocket, services: str, tail: int = DEFAULT_TAIL, t
if __name__ == "__main__":
import uvicorn
print(f"LogBoard+ http://0.0.0.0:{APP_PORT}")
uvicorn.run(app, host="0.0.0.0", port=APP_PORT)
print(f"Debug mode: {'ON' if DEBUG_MODE else 'OFF'}")
if DEBUG_MODE:
print("Swagger UI: http://0.0.0.0:{}/docs".format(APP_PORT))
print("ReDoc: http://0.0.0.0:{}/redoc".format(APP_PORT))
uvicorn.run(
app,
host="0.0.0.0",
port=APP_PORT,
reload=DEBUG_MODE,
log_level="debug" if DEBUG_MODE else "info"
)