Skip to content

Commit 902454d

Browse files
committed
Updates to compose_down command to match docker compose behavior
Signed-off-by: Yashodhan Pise <[email protected]>
1 parent 2edd4f3 commit 902454d

File tree

1 file changed

+68
-29
lines changed

1 file changed

+68
-29
lines changed

podman_compose.py

+68-29
Original file line numberDiff line numberDiff line change
@@ -2869,13 +2869,32 @@ def get_volume_names(compose, cnt):
28692869

28702870
@cmd_run(podman_compose, "down", "tear down entire stack")
28712871
async def compose_down(compose: PodmanCompose, args):
2872+
# get_excluded fails as no-deps is not a supported cli arg
28722873
excluded = get_excluded(compose, args)
28732874
podman_args = []
28742875
timeout_global = getattr(args, "timeout", None)
28752876
containers = list(reversed(compose.containers))
28762877

2877-
down_tasks = []
2878+
# Get list of currently running containers
2879+
running_cnt_names = (
2880+
(
2881+
await compose.podman.output(
2882+
[],
2883+
"ps",
2884+
[
2885+
"--filter",
2886+
f"label=io.podman.compose.project={compose.project_name}",
2887+
"-a",
2888+
"--format",
2889+
"{{ .Names }}",
2890+
],
2891+
)
2892+
)
2893+
.decode("utf-8")
2894+
.splitlines()
2895+
)
28782896

2897+
stop_tasks = []
28792898
for cnt in containers:
28802899
if cnt["_service"] in excluded:
28812900
continue
@@ -2886,38 +2905,58 @@ async def compose_down(compose: PodmanCompose, args):
28862905
timeout = str_to_seconds(timeout_str)
28872906
if timeout is not None:
28882907
podman_stop_args.extend(["-t", str(timeout)])
2889-
down_tasks.append(
2890-
asyncio.create_task(
2891-
compose.podman.run([], "stop", [*podman_stop_args, cnt["name"]]), name=cnt["name"]
2892-
)
2893-
)
2894-
await asyncio.gather(*down_tasks)
2908+
stop_tasks.append(compose.podman.run([], "stop", [*podman_stop_args, cnt["name"]]))
2909+
await asyncio.gather(*stop_tasks)
2910+
stop_tasks.clear()
2911+
2912+
rm_tasks = []
28952913
for cnt in containers:
28962914
if cnt["_service"] in excluded:
28972915
continue
2898-
await compose.podman.run([], "rm", [cnt["name"]])
2916+
rm_tasks.append(compose.podman.run([], "rm", [cnt["name"]]))
2917+
if cnt["name"] in running_cnt_names:
2918+
running_cnt_names.remove(cnt["name"])
2919+
await asyncio.gather(*rm_tasks)
2920+
rm_tasks.clear()
2921+
2922+
# The logic is updated based on docker compose documentation:
2923+
# `--remove-orphans`: Remove containers for services not defined in the Compose file
2924+
# Ref: https://docs.docker.com/reference/cli/docker/compose/down/#options
2925+
orphan_cnt_names = []
2926+
for cnt in running_cnt_names:
2927+
if not any(f"{compose.project_name}_{service}_" in cnt for service in compose.all_services):
2928+
orphan_cnt_names.append(cnt)
2929+
running_cnt_names.remove(cnt)
2930+
2931+
# We list the containers and remove them from running container list
2932+
# However, we stop them only if provided with CLI arg `--remove-orphans`
28992933
if args.remove_orphans:
2900-
names = (
2901-
(
2902-
await compose.podman.output(
2903-
[],
2904-
"ps",
2905-
[
2906-
"--filter",
2907-
f"label=io.podman.compose.project={compose.project_name}",
2908-
"-a",
2909-
"--format",
2910-
"{{ .Names }}",
2911-
],
2912-
)
2913-
)
2914-
.decode("utf-8")
2915-
.splitlines()
2916-
)
2917-
for name in names:
2918-
await compose.podman.run([], "stop", [*podman_args, name])
2919-
for name in names:
2920-
await compose.podman.run([], "rm", [name])
2934+
for name in orphan_cnt_names:
2935+
stop_tasks.append(compose.podman.run([], "stop", [*podman_args, name]))
2936+
await asyncio.gather(*stop_tasks)
2937+
stop_tasks.clear()
2938+
2939+
for name in orphan_cnt_names:
2940+
rm_tasks.append(compose.podman.run([], "rm", [name]))
2941+
await asyncio.gather(*rm_tasks)
2942+
rm_tasks.clear()
2943+
2944+
for cnt in running_cnt_names:
2945+
# This logic goes away if the containers list can be updated accordingly at source
2946+
# Clear containers not formed out of the current compose file definitions
2947+
# E.g.: By using CLI `up --scale <APP>=<NUM>` option
2948+
podman_stop_args = [*podman_args]
2949+
if timeout_global is not None:
2950+
podman_stop_args.extend(["-t", str(timeout_global)])
2951+
stop_tasks.append(compose.podman.run([], "stop", [*podman_stop_args, cnt]))
2952+
await asyncio.gather(*stop_tasks)
2953+
stop_tasks.clear()
2954+
2955+
for cnt in running_cnt_names:
2956+
rm_tasks.append(compose.podman.run([], "rm", [cnt]))
2957+
await asyncio.gather(*rm_tasks)
2958+
rm_tasks.clear()
2959+
29212960
if args.volumes:
29222961
vol_names_to_keep = set()
29232962
for cnt in containers:

0 commit comments

Comments
 (0)