@@ -9,14 +9,15 @@ def list_running_containers():
99 """
1010 try :
1111 client = docker .from_env ()
12- containers = client .containers .list ()
12+ containers = client .containers .list (all = True ) # Get all containers, not just running, to see labels of stopped ones too
1313 container_list = []
1414 for container in containers :
1515 container_list .append ({
1616 "id" : container .short_id ,
1717 "name" : container .name ,
1818 "image" : container .attrs ['Config' ]['Image' ],
19- "status" : container .status
19+ "status" : container .status ,
20+ "labels" : container .labels # Add labels
2021 })
2122 if not container_list :
2223 return "No running containers found."
@@ -26,6 +27,37 @@ def list_running_containers():
2627 except Exception as e :
2728 return f"An unexpected error occurred: { str (e )} "
2829
30+ def get_grouped_docker_compose_projects ():
31+ """
32+ Lists containers and groups them by the 'com.docker.compose.project' label.
33+ Returns a dictionary where keys are compose project names and values are lists of container dicts.
34+ Containers without the project label are grouped under '__ungrouped__'.
35+ """
36+ containers_or_error = list_running_containers () # This now includes labels
37+ if isinstance (containers_or_error , str ):
38+ return containers_or_error # Return error message if fetching containers failed
39+
40+ grouped_projects = {}
41+ for container in containers_or_error :
42+ project_name = container .get ("labels" , {}).get ("com.docker.compose.project" )
43+ # Also consider com.docker.compose.project.name for some compose versions/setups
44+ if not project_name :
45+ project_name = container .get ("labels" , {}).get ("com.docker.compose.project.name" )
46+
47+ if project_name :
48+ if project_name not in grouped_projects :
49+ grouped_projects [project_name ] = []
50+ grouped_projects [project_name ].append (container )
51+ else :
52+ if '__ungrouped__' not in grouped_projects :
53+ grouped_projects ['__ungrouped__' ] = []
54+ grouped_projects ['__ungrouped__' ].append (container )
55+
56+ # Convert to a list of dicts for easier frontend consumption if preferred, or keep as dict
57+ # Example: [{ "projectName": "my_project", "containers": [...] }]
58+ # For now, returning the dictionary direkte
59+ return grouped_projects
60+
2961def get_container_code_paths (container_id : str ):
3062 """
3163 Retrieves the host paths for volume mounts of a given container.
@@ -65,23 +97,37 @@ def get_container_code_paths(container_id: str):
6597
6698if __name__ == '__main__' :
6799 print ("Attempting to list running containers..." )
68- running_containers = list_running_containers ()
69- if isinstance (running_containers , str ): # Error message
70- print (running_containers )
71- elif running_containers :
72- print ("Running containers:" )
73- for cont in running_containers :
74- print (f" ID: { cont ['id' ]} , Name: { cont ['name' ]} , Image: { cont ['image' ]} , Status: { cont ['status' ]} " )
75- print (f" Attempting to get code paths for { cont ['id' ]} ({ cont ['name' ]} )..." )
76- paths = get_container_code_paths (cont ['id' ])
77- if isinstance (paths , str ): # Error message
78- print (f" Error/Info: { paths } " )
79- elif paths :
80- print (" Found potential host paths:" )
81- for path in paths :
82- print (f" - { path } " )
83- else : # Empty list but no error string
84- print (f" No specific host paths identified for { cont ['id' ]} ." )
100+ # Test the new grouping function
101+ grouped_containers = get_grouped_docker_compose_projects ()
102+ if isinstance (grouped_containers , str ):
103+ print (f"Error getting grouped projects: { grouped_containers } " )
104+ else :
105+ print ("\n Grouped Docker Compose Projects:" )
106+ for project_name , containers_in_project in grouped_containers .items ():
107+ print (f" Project: { project_name } " )
108+ for cont in containers_in_project :
109+ print (f" - ID: { cont ['id' ]} , Name: { cont ['name' ]} , Status: { cont ['status' ]} , Image: { cont ['image' ]} " )
110+ # Optional: print labels for verification
111+ # print(f" Labels: {cont['labels']}")
85112
86- else : # Empty list from list_running_containers, but not an error string.
87- print ("No running containers were found to inspect." )
113+ # Original test for list_running_containers and get_container_code_paths (can be kept for direct testing)
114+ # running_containers = list_running_containers()
115+ # if isinstance(running_containers, str): # Error message
116+ # print(running_containers)
117+ # elif running_containers:
118+ # print("\nIndividual Running containers (for path testing):")
119+ # for cont in running_containers:
120+ # if cont['status'] == 'running': # Only try to get paths for actually running containers for this test part
121+ # print(f" ID: {cont['id']}, Name: {cont['name']}")
122+ # print(f" Attempting to get code paths for {cont['id']} ({cont['name']})...")
123+ # paths = get_container_code_paths(cont['id'])
124+ # if isinstance(paths, str): # Error message
125+ # print(f" Error/Info: {paths}")
126+ # elif paths:
127+ # print(" Found potential host paths:")
128+ # for path in paths:
129+ # print(f" - {path}")
130+ # else: # Empty list but no error string
131+ # print(f" No specific host paths identified for {cont['id']}.")
132+ # else: # Empty list from list_running_containers, but not an error string.
133+ # print("No running containers were found to inspect for paths.")
0 commit comments