From 7d3a09bf5eae4d50c70a58e38fb5433160f5ae20 Mon Sep 17 00:00:00 2001 From: Bryan Gin-ge Chen Date: Wed, 21 Oct 2026 00:51:35 -0400 Subject: [PATCH] fix(docker): stop leaving anonymous volumes behind Three places left a Docker volume on the machine each time they ran, and nothing referenced it afterwards: - scripts/test_download_s3_dump.sh removed its Postgres 18 and 17 containers with `docker rm -f`, which keeps their anonymous volumes: two Postgres data directories per run. - scripts/local_sanitize_backup.sh does the same. --rm deletes the volume only when the container stops on its own, so each run left a full copy of the restored database. - Compose's redis service had no mount at /data, where the image declares a volume, so each new container got a new anonymous one, which `docker compose down` (as scripts/repo_check_compose.sh runs it) left behind. Redis now keeps /data on a tmpfs: it holds only the broker's queue and the app's short-lived keys, which it can lose, and it was already empty after each `down`. Tested: test_download_s3_dump.sh passes, and leaves Docker's volumes, networks and containers as it found them. So does local_sanitize_backup.sh when its restore fails, after the container has started. Redis starts healthy with only the tmpfs at /data, and `docker compose down` leaves nothing. Co-Authored-By: Claude Opus 5.5 --- docker-compose.yml | 5 +++++ scripts/local_sanitize_backup.sh | 4 +++- scripts/test_download_s3_dump.sh | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 313b23e0..0fc5a211 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -107,6 +107,11 @@ services: redis: image: redis:7-alpine + # In memory. The image declares a volume at /data, so without a mount there each new + # container got a new anonymous volume, which `docker compose down` left behind. Redis holds + # only the broker's queue and the app's short-lived keys, which it can lose. + tmpfs: + - /data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s diff --git a/scripts/local_sanitize_backup.sh b/scripts/local_sanitize_backup.sh index 4dcf59b4..818c6169 100755 --- a/scripts/local_sanitize_backup.sh +++ b/scripts/local_sanitize_backup.sh @@ -78,7 +78,9 @@ DB_URL="postgres://postgres:postgres@localhost:${PORT}/${DB_NAME}" cleanup() { if [[ $CONTAINER_STARTED -eq 1 ]]; then echo "Stopping container ${CONTAINER}..." - docker rm -f "$CONTAINER" >/dev/null 2>&1 || true + # -v: --rm deletes the data volume only when the container stops on its own, and removing + # it here would otherwise leave a copy of the restored database behind. + docker rm -f -v "$CONTAINER" >/dev/null 2>&1 || true fi } trap cleanup EXIT diff --git a/scripts/test_download_s3_dump.sh b/scripts/test_download_s3_dump.sh index 6ac91032..2134caa8 100755 --- a/scripts/test_download_s3_dump.sh +++ b/scripts/test_download_s3_dump.sh @@ -25,7 +25,8 @@ LARGE_DUMP_BYTES=$((9 * 1024 * 1024)) run="qb-s3-dump-test-$$" work="$(mktemp -d)" cleanup() { - docker rm -f "$run-s3" "$run-pg18" "$run-pg17" >/dev/null 2>&1 || true + # -v: with their anonymous volumes, such as each Postgres's data directory. + docker rm -f -v "$run-s3" "$run-pg18" "$run-pg17" >/dev/null 2>&1 || true rm -rf "$work" } trap cleanup EXIT