diff --git a/app.py b/app.py index 1722969..e5a08b4 100644 --- a/app.py +++ b/app.py @@ -17,6 +17,7 @@ DEFAULT_TAIL = int(os.getenv("LOGBOARD_TAIL", "500")) BASIC_USER = os.getenv("LOGBOARD_USER", "admin") BASIC_PASS = os.getenv("LOGBOARD_PASS", "admin") DEFAULT_PROJECT = os.getenv("COMPOSE_PROJECT_NAME") # filter by compose project +DEFAULT_PROJECTS = os.getenv("LOGBOARD_PROJECTS") # multiple projects filter SKIP_UNHEALTHY = os.getenv("LOGBOARD_SKIP_UNHEALTHY", "true").lower() == "true" CONTAINER_LIST_TIMEOUT = int(os.getenv("LOGBOARD_CONTAINER_LIST_TIMEOUT", "10")) CONTAINER_INFO_TIMEOUT = int(os.getenv("LOGBOARD_CONTAINER_INFO_TIMEOUT", "3")) @@ -51,9 +52,48 @@ def verify_ws_token(token: str) -> bool: return raw == f"{BASIC_USER}:{BASIC_PASS}" # ---------- DOCKER HELPERS ---------- -def list_containers(project: Optional[str] = None, include_stopped: bool = False) -> List[Dict]: +def get_all_projects() -> List[str]: """ - Получает список контейнеров с упрощенной логикой для предотвращения зависания + Получает список всех проектов Docker Compose + Автор: Сергей Антропов + Сайт: https://devops.org.ru + """ + projects = set() + + try: + containers = docker_client.containers.list(all=True) + + for c in containers: + try: + labels = c.labels or {} + project = labels.get("com.docker.compose.project") + if project: + projects.add(project) + except Exception: + continue + + # Добавляем контейнеры без проекта как "standalone" + standalone_count = 0 + for c in containers: + try: + labels = c.labels or {} + if not labels.get("com.docker.compose.project"): + standalone_count += 1 + except Exception: + continue + + if standalone_count > 0: + projects.add("standalone") + + except Exception as e: + print(f"❌ Ошибка получения списка проектов: {e}") + return [] + + return sorted(list(projects)) + +def list_containers(projects: Optional[List[str]] = None, include_stopped: bool = False) -> List[Dict]: + """ + Получает список контейнеров с поддержкой множественных проектов Автор: Сергей Антропов Сайт: https://devops.org.ru """ @@ -93,9 +133,12 @@ def list_containers(project: Optional[str] = None, include_stopped: bool = False except Exception: pass # Оставляем "unknown" - # Фильтрация по проекту - if project and basic_info["project"] != project: - continue + # Фильтрация по проектам + if projects: + # Если проект не указан, считаем его standalone + container_project = basic_info["project"] or "standalone" + if container_project not in projects: + continue # Добавляем контейнер в список items.append(basic_info) @@ -130,11 +173,27 @@ def index(creds: HTTPBasicCredentials = Depends(check_basic)): def healthz(): return "ok" +@app.get("/api/projects") +def api_projects(_: HTTPBasicCredentials = Depends(check_basic)): + """Получить список всех проектов Docker Compose""" + return JSONResponse(get_all_projects()) + @app.get("/api/services") -def api_services(project: Optional[str] = Query(None), include_stopped: bool = Query(False), +def api_services(projects: Optional[str] = Query(None), include_stopped: bool = Query(False), _: HTTPBasicCredentials = Depends(check_basic)): - proj = project or DEFAULT_PROJECT - return JSONResponse(list_containers(project=proj, include_stopped=include_stopped)) + """ + Получить список контейнеров с поддержкой множественных проектов + projects: список проектов через запятую (например: "project1,project2") + """ + project_list = None + if projects: + project_list = [p.strip() for p in projects.split(",") if p.strip()] + elif DEFAULT_PROJECTS: + project_list = [p.strip() for p in DEFAULT_PROJECTS.split(",") if p.strip()] + elif DEFAULT_PROJECT: + project_list = [DEFAULT_PROJECT] + + return JSONResponse(list_containers(projects=project_list, include_stopped=include_stopped)) @app.post("/api/snapshot") def api_snapshot( diff --git a/env.example b/env.example index c49af5c..a82e6ae 100644 --- a/env.example +++ b/env.example @@ -20,6 +20,10 @@ TZ_TS= # Фильтр по проекту Docker Compose (опционально) # COMPOSE_PROJECT_NAME=myproj +# Настройки множественных проектов +# Укажите проекты через запятую для отображения контейнеров из нескольких проектов +# LOGBOARD_PROJECTS=project1,project2,project3 + # Настройки Docker DOCKER_HOST=unix:///var/run/docker.sock DOCKER_TLS_VERIFY= diff --git a/templates/index.html b/templates/index.html index 7383cf8..2c97492 100644 --- a/templates/index.html +++ b/templates/index.html @@ -73,6 +73,11 @@ footer{position:fixed;right:10px;bottom:10px;opacity:.6;font-size:11px}