import docker client = docker.from_env() running_containers = [] for c in client.containers.list(): # только запущенные контейнеры info = c.attrs # словарь со всеми данными image = info["Config"]["Image"] # образ created = info["Created"] # время создания ports = info["NetworkSettings"]["Ports"] # проброшенные порты mounts = info.get("Mounts", []) # маунты status = c.status # статус контейнера (д.б. "running") labels_container = info["Config"].get("Labels", {}) or {} image_cfg = c.image.attrs.get("Config", {}) or {} image_labels = image_cfg.get("Labels", {}) or {} all_labels = {**image_labels, **labels_container} source_url = ( all_labels.get("org.opencontainers.image.source") or all_labels.get("org.opencontainers.image.url") or all_labels.get("org.opencontainers.image.documentation") or all_labels.get("org.label-schema.vcs-url") or all_labels.get("org.label-schema.url") ) source_revision = ( all_labels.get("org.opencontainers.image.revision") or all_labels.get("org.label-schema.vcs-ref") ) image_version_label = ( all_labels.get("org.opencontainers.image.version") or all_labels.get("org.label-schema.version") ) # Версия из тега образа tags = c.image.tags if tags: ver = tags[0].split(":", 1)[-1] else: ver = None # Рабочая директория workdir = info["Config"].get("WorkingDir") or "/" # Поиск файлов зависимостей req_paths = [] language = None req_find_cmd = ( f"cd {workdir} 2>/dev/null || cd /; " "find . -maxdepth 3 \\( " "-name 'requirements*.txt' -o " "-name 'Pipfile' -o " "-name 'pyproject.toml' -o " "-name 'package.json' -о " "-name 'go.mod' " "\\) 2>/dev/null | head -n 5" ) req_res = c.exec_run(["sh", "-lc", req_find_cmd]) if req_res.exit_code == 0: req_out = req_res.output.decode(errors="ignore") req_paths = [line.strip() for line in req_out.splitlines() if line.strip()] else: req_paths = [] # Определяем язык по файлам зависимостей for p in req_paths: lower = p.lower() if "requirements" in lower or p.endswith("Pipfile") or p.endswith("pyproject.toml"): language = "python" break if p.endswith("package.json"): language = "nodejs" break if p.endswith("go.mod"): language = "go" break # Поиск "главных" файлов кода code_paths = [] code_find_cmd = ( f"cd {workdir} 2>/dev/null || cd /; " "find . -maxdepth 4 -type f \\( " "-name 'main.*' -о " "-name 'app.*' -o " "-name 'index.*' " "\\) 2>/dev/null | head -n 10" ) code_res = c.exec_run(["sh", "-lc", code_find_cmd]) if code_res.exit_code == 0: code_out = code_res.output.decode(errors="ignore") code_paths = [line.strip() for line in code_out.splitlines() if line.strip()] else: code_paths = [] # Если по зависимостям язык не определился — пробуем по расширениям файлов кода if language is None: for p in code_paths: p_lower = p.lower() if p_lower.endswith(".py"): language = "python" break if p_lower.endswith(".js") or p_lower.endswith(".mjs") or p_lower.endswith(".cjs"): language = "nodejs" break if p_lower.endswith(".php"): language = "php" break if p_lower.endswith(".rb"): language = "ruby" break if p_lower.endswith(".go"): language = "go" break if p_lower.endswith(".rs"): language = "rust" break if p_lower.endswith(".java"): language = "java" break container_data = { "name": c.name, "version": ver, "image": image, "id": c.id[:12], "create_time": created, "mounted_data": mounts, "labels": labels_container, "all_labels": all_labels, "source_url": source_url, "source_revision": source_revision, "image_version_label": image_version_label, "language": language, "dep_files": req_paths, "code_files": code_paths, } running_containers.append(container_data) # Проверочный вывод for c in running_containers: print(f"{c['name']} ({c['image']})") print(f" id: {c['id']}, created: {c['create_time']}") print(f" tag_version: {c['version']}, label_version: {c['image_version_label']}") print(f" language: {c['language']}") print(f" source: {c['source_url']} rev: {c['source_revision']}") print(f" dep_files: {c['dep_files']}") print(f" code_files: {c['code_files']}") print()