From 4927ca092d427143b368f744421a2392df86b9a0 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Mon, 27 Apr 2026 01:20:24 -0400 Subject: [PATCH 1/2] fix: retire orphaned containers when scaling down When scaling a process type to a smaller count, the indices above the new count had their `CONTAINER..` state files deleted but the underlying Docker containers were never registered for retirement, so they remained running indefinitely. The cleanup block now reads each orphaned state file and registers its container id with the existing `scheduler-register-retired` trigger before the file is removed. --- .../bin/scheduler-deploy-process | 9 +++- tests/unit/scheduler-docker-local.bats | 44 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/plugins/scheduler-docker-local/bin/scheduler-deploy-process b/plugins/scheduler-docker-local/bin/scheduler-deploy-process index 4d4ed744d..bc567deb9 100755 --- a/plugins/scheduler-docker-local/bin/scheduler-deploy-process +++ b/plugins/scheduler-docker-local/bin/scheduler-deploy-process @@ -85,8 +85,15 @@ fn-scheduler-deploy-process() { else local CONTAINER_IDX_OFFSET=$((PROC_COUNT + 1)) fi - local container_state_filetype + local container_state_filetype orphaned_container_file orphaned_cid pushd "$DOKKU_ROOT/$APP" >/dev/null + for orphaned_container_file in $(find . -maxdepth 1 -name "CONTAINER.$PROC_TYPE.*" -printf "%f\n" | sort -t . -k 3 -n | tail -n +$CONTAINER_IDX_OFFSET); do + [[ -s "$orphaned_container_file" ]] || continue + orphaned_cid="$(<"$orphaned_container_file")" + [[ -z "$orphaned_cid" ]] && continue + dokku_log_verbose "Scheduling orphaned container shutdown in $DOKKU_WAIT_TO_RETIRE seconds (${orphaned_container_file#CONTAINER.})" + plugn trigger scheduler-register-retired "$APP" "$orphaned_cid" "$DOKKU_WAIT_TO_RETIRE" + done for container_state_filetype in CONTAINER IP PORT; do find . -maxdepth 1 -name "$container_state_filetype.$PROC_TYPE.*" -printf "%f\n" | sort -t . -k 3 -n | tail -n +$CONTAINER_IDX_OFFSET | xargs rm -f done diff --git a/tests/unit/scheduler-docker-local.bats b/tests/unit/scheduler-docker-local.bats index d14ea9ed4..4af6c279d 100644 --- a/tests/unit/scheduler-docker-local.bats +++ b/tests/unit/scheduler-docker-local.bats @@ -175,3 +175,47 @@ teardown() { assert_output_contains "Deploys may fail when publishing ports and scaling to multiple containers" 0 assert_output_contains "Deploys may fail when publishing ports and enabling zero downtime" 0 } + +@test "(scheduler-docker-local) scale down retires orphaned containers" { + run create_app + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku checks:set $TEST_APP wait-to-retire 1" + echo "output: $output" + echo "status: $status" + assert_success + + run deploy_app + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku ps:scale $TEST_APP web=2" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker ps --filter label=com.dokku.app-name=$TEST_APP --filter label=com.dokku.process-type=web --format '{{.Names}}' | wc -l" + echo "output: $output" + echo "status: $status" + assert_output "2" + + run /bin/bash -c "dokku ps:scale $TEST_APP web=1" + echo "output: $output" + echo "status: $status" + assert_success + + sleep 2 + + run /bin/bash -c "dokku ps:retire" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker ps --filter label=com.dokku.app-name=$TEST_APP --filter label=com.dokku.process-type=web --format '{{.Names}}'" + echo "output: $output" + echo "status: $status" + assert_output "$TEST_APP.web.1" +} From bc603d7b9c56c7aae40dda9c942a15f415077d26 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Mon, 27 Apr 2026 03:29:06 -0400 Subject: [PATCH 2/2] test: drain dead-containers before scale-up assertion The intermediate container count check raced with the existing zero-downtime retire of the previous container, so docker ps still saw the renamed-but-pending container until wait-to-retire elapsed. --- tests/unit/scheduler-docker-local.bats | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/unit/scheduler-docker-local.bats b/tests/unit/scheduler-docker-local.bats index 4af6c279d..fe9e9531d 100644 --- a/tests/unit/scheduler-docker-local.bats +++ b/tests/unit/scheduler-docker-local.bats @@ -197,6 +197,13 @@ teardown() { echo "status: $status" assert_success + sleep 2 + + run /bin/bash -c "dokku ps:retire" + echo "output: $output" + echo "status: $status" + assert_success + run /bin/bash -c "docker ps --filter label=com.dokku.app-name=$TEST_APP --filter label=com.dokku.process-type=web --format '{{.Names}}' | wc -l" echo "output: $output" echo "status: $status"