Skip to content

fix: remove stopped containers referencing a volume before restore - #5225

Open
Siumauricio wants to merge 3 commits into
canaryfrom
fix/issue-3995-volume-restore-stopped-container
Open

fix: remove stopped containers referencing a volume before restore#5225
Siumauricio wants to merge 3 commits into
canaryfrom
fix/issue-3995-volume-restore-stopped-container

Conversation

@Siumauricio

@Siumauricio Siumauricio commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Fixes #3995

Volume restore aborted with "volume is in use" whenever a stopped/exited container still referenced the target volume, forcing users to SSH in and manually remove the container before restoring. This is common after stopping a compose service from the UI — Docker keeps the exited container attached to the volume.

Change

In restoreVolume's in-use check, containers referencing the volume are now split into running vs stopped:

  • Running containers still abort the restore with the existing warning (unchanged, safe behavior).
  • Stopped containers are removed automatically (docker rm -f) before the volume is recreated and the restore proceeds.

Verified

Reproduced end-to-end against a local Dokploy instance (Playwright UI + real Docker):

  1. Deployed a compose service with a named volume, took a manual volume backup.
  2. Stopped the service — container went exited but kept referencing the volume.
  3. Confirmed the bug: restore aborted with the "volume is in use" error.
  4. Applied the fix and reran the restore: log showed the stopped container being removed, then the volume was recreated and restored successfully, with no manual SSH step.
  5. Confirmed via Docker that the old container was gone and the volume contained the restored backup files.

Greptile Summary

This PR allows volume restores to remove containers considered stopped before recreating the target volume.

  • Splits attached containers into running and non-running groups.
  • Preserves the abort path for containers reported as running.
  • Force-removes non-running containers and then restores the volume from backup.

Confidence Score: 2/5

The PR is not safe to merge until automatic removal is restricted to confirmed stopped containers and all destructive preconditions are revalidated and enforced.

The changed restore path can force-delete paused, restarting, or concurrently started containers, and ignored cleanup failures can make an overlay extraction into the old volume appear successful.

Files Needing Attention: packages/server/src/utils/volume-backups/restore.ts

Reviews (1): Last reviewed commit: "fix: remove stopped containers referenci..." | Re-trigger Greptile

Greptile also left 3 inline comments on this PR.

Context used:

Volume restore aborted with "volume is in use" whenever a stopped
container still referenced the target volume, forcing users to SSH in
and remove it manually. Running containers still block the restore,
but stopped ones are now removed automatically before the volume is
recreated.

Fixes #3995
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Aug 30, 2026
Comment on lines +69 to +70
RUNNING_CONTAINERS=$(echo "$CONTAINERS_USING_VOLUME" | awk -F'|' '$3 == "running"')
STOPPED_CONTAINERS=$(echo "$CONTAINERS_USING_VOLUME" | awk -F'|' '$3 != "running"')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Active states classified as stopped

When a volume-referencing container is paused or restarting, $3 != "running" classifies it as stopped and passes it to docker rm -f, causing an active workload to be forcibly deleted before its volume is replaced.

Knowledge Base Used:

Comment on lines +110 to +117
echo "$STOPPED_CONTAINERS" | while IFS='|' read container_id container_name container_state labels; do
echo " 🗑 Removing stopped container: $container_name ($container_id) [status: $container_state]"
docker rm -f "$container_id" >/dev/null 2>&1 || true
done

echo ""
echo "❌ Volume restore aborted - volume is in use"

exit 1
echo "Removing existing volume and proceeding with restore"
docker volume rm ${volumeName} --force

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Removal failures permit mixed restores

When docker rm -f leaves a container attached, || true suppresses the error and the script also continues after the resulting volume-removal failure. The restore then extracts into the existing volume, leaving files absent from the backup in place while reporting a successful restore.

Knowledge Base Used:

Comment on lines +110 to +112
echo "$STOPPED_CONTAINERS" | while IFS='|' read container_id container_name container_state labels; do
echo " 🗑 Removing stopped container: $container_name ($container_id) [status: $container_state]"
docker rm -f "$container_id" >/dev/null 2>&1 || true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Stale state permits forced removal

If a stopped container starts after the one-time docker ps -a snapshot, the removal loop does not recheck its state before invoking docker rm -f, causing the newly active workload to be deleted while restore proceeds toward replacing its volume.

Knowledge Base Used: Backups and restore

- Only treat exited/created/dead containers as safely removable;
  paused/restarting/removing containers now still block the restore
  like a running one does.
- Re-check each container's live state right before removing it, to
  avoid deleting one that started running again after the initial
  docker ps -a snapshot.
- Stop swallowing docker rm/docker volume rm failures with '|| true';
  abort the restore instead of silently continuing and extracting
  into a volume that may still be attached to a container.
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:M This PR changes 30-99 lines, ignoring generated files. labels Aug 30, 2026
The restore script runs under /bin/sh, not bash. Process substitution
("< <(...)") is a bashism dash doesn't support, so the previous fix
failed at runtime with a syntax error and the restore never ran.
Write STOPPED_CONTAINERS to a temp file and read the while loops from
that instead — same effect, works under plain POSIX sh.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Volume Restore Fails: Stopped Container Still References Volume, Requires Manual SSH to Restore

1 participant