Skip to content

Commit 2f5a464

Browse files
committed
Updates to compose_down command to match docker compose behavior (Issue: containers#267)
Signed-off-by: Yashodhan Pise <[email protected]>
1 parent 29ebc63 commit 2f5a464

File tree

1 file changed

+50
-26
lines changed

1 file changed

+50
-26
lines changed

podman_compose.py

+50-26
Original file line numberDiff line numberDiff line change
@@ -2854,12 +2854,30 @@ def get_volume_names(compose, cnt):
28542854

28552855
@cmd_run(podman_compose, "down", "tear down entire stack")
28562856
async def compose_down(compose: PodmanCompose, args):
2857+
# get_excluded fails as no-deps is not a supported cli arg
28572858
excluded = get_excluded(compose, args)
28582859
podman_args = []
28592860
timeout_global = getattr(args, "timeout", None)
28602861
containers = list(reversed(compose.containers))
28612862

2862-
down_tasks = []
2863+
# Get list of currently running containers
2864+
running_cnt_names = (
2865+
(
2866+
await compose.podman.output(
2867+
[],
2868+
"ps",
2869+
[
2870+
"--filter",
2871+
f"label=io.podman.compose.project={compose.project_name}",
2872+
"-a",
2873+
"--format",
2874+
"{{ .Names }}",
2875+
],
2876+
)
2877+
)
2878+
.decode("utf-8")
2879+
.splitlines()
2880+
)
28632881

28642882
for cnt in containers:
28652883
if cnt["_service"] in excluded:
@@ -2871,38 +2889,44 @@ async def compose_down(compose: PodmanCompose, args):
28712889
timeout = str_to_seconds(timeout_str)
28722890
if timeout is not None:
28732891
podman_stop_args.extend(["-t", str(timeout)])
2874-
down_tasks.append(
2875-
asyncio.create_task(
2876-
compose.podman.run([], "stop", [*podman_stop_args, cnt["name"]]), name=cnt["name"]
2877-
)
2878-
)
2879-
await asyncio.gather(*down_tasks)
2892+
await compose.podman.run([], "stop", [*podman_stop_args, cnt["name"]])
2893+
28802894
for cnt in containers:
28812895
if cnt["_service"] in excluded:
28822896
continue
28832897
await compose.podman.run([], "rm", [cnt["name"]])
2898+
if cnt["name"] in running_cnt_names:
2899+
running_cnt_names.remove(cnt["name"])
2900+
2901+
# The logic is updated based on docker compose documentation:
2902+
# `--remove-orphans`: Remove containers for services not defined in the Compose file
2903+
# Ref: https://docs.docker.com/reference/cli/docker/compose/down/#options
2904+
orphan_cnt_names = []
2905+
for cnt in running_cnt_names:
2906+
if not any(f"{compose.project_name}_{service}_" in cnt for service in compose.all_services):
2907+
orphan_cnt_names.append(cnt)
2908+
running_cnt_names.remove(cnt)
2909+
2910+
# We list the containers and remove them from running container list
2911+
# However, we stop them only if porvided with CLI arg `--remove-orphans`
28842912
if args.remove_orphans:
2885-
names = (
2886-
(
2887-
await compose.podman.output(
2888-
[],
2889-
"ps",
2890-
[
2891-
"--filter",
2892-
f"label=io.podman.compose.project={compose.project_name}",
2893-
"-a",
2894-
"--format",
2895-
"{{ .Names }}",
2896-
],
2897-
)
2898-
)
2899-
.decode("utf-8")
2900-
.splitlines()
2901-
)
2902-
for name in names:
2913+
for name in orphan_cnt_names:
29032914
await compose.podman.run([], "stop", [*podman_args, name])
2904-
for name in names:
2915+
for name in orphan_cnt_names:
29052916
await compose.podman.run([], "rm", [name])
2917+
2918+
for cnt in running_cnt_names:
2919+
# This logic goes away if the containers list can be updated accordingly at source
2920+
# Clear containers not formed out of the current compose file definitions
2921+
# E.g.: By using CLI `up --scale <APP>=<NUM>` option
2922+
podman_stop_args = [*podman_args]
2923+
if timeout_global is not None:
2924+
podman_stop_args.extend(["-t", str(timeout_global)])
2925+
await compose.podman.run( [], "stop", [*podman_stop_args, cnt])
2926+
2927+
for cnt in running_cnt_names:
2928+
await compose.podman.run([], "rm", [cnt])
2929+
29062930
if args.volumes:
29072931
vol_names_to_keep = set()
29082932
for cnt in containers:

0 commit comments

Comments
 (0)