From 91fcbc5adce1e77e745b28e90b8a876b0e3b4b2b Mon Sep 17 00:00:00 2001 From: Kpa-clawbot <259247574+Kpa-clawbot@users.noreply.github.com> Date: Sat, 28 Mar 2026 16:01:16 -0700 Subject: [PATCH] Fix: Use bind mounts instead of named volumes for data directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PROBLEM: manage.sh was using named Docker volumes (meshcore-data) as the default, which hides the database and theme files inside Docker's internal storage. Users couldn't find their DB on the filesystem for backups or inspection. The function get_data_mount_args() had conditional logic that only used bind mounts IF it detected an existing ~/meshcore-data with a DB file. For new installs, it fell through to the named volume — silently hiding all data in /var/lib/docker/volumes/. FIXES: 1. get_data_mount_args() — Always use bind mount to ~/meshcore-data - Creates the directory if it doesn't exist - Removes all conditional logic and the named volume fallback 2. cmd_backup() — Use direct path C:\Users\KpaBap/meshcore-data/meshcore.db - No longer tries to inspect the named volume - Consistent with the bind mount approach 3. cmd_restore() — Use direct path for restore operations - Ensures directory exists before restoring files - No fallback to docker cp 4. cmd_reset() — Updated message to reflect bind mount location - Changed from 'docker volume rm' to '~/meshcore-data (not removed)' 5. docker-compose.yml — Added documentation comment - Clarifies that bind mounts are intentional, not named volumes - Ensures future changes maintain this pattern VALIDATION: - docker-compose.yml already used bind mounts correctly (\) - Legacy 'docker run' mode now matches compose behavior - All backup/restore operations reference the same bind mount path DATABASE LOCATION: - Always: ~/meshcore-data/meshcore.db - Never: Hidden in Docker's volume storage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Requested-by: Kpa-clawbot --- docker-compose.yml | 4 +++- manage.sh | 41 ++++++++++++++++------------------------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 27d5360c..32e97f12 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,7 @@ -# Volume paths unified with manage.sh — see manage.sh lines 9-12, 56-68, 98-113 +# Volume paths unified with manage.sh — see manage.sh lines 9-12, 55-62, 920, 944 # Override defaults via .env or environment variables. +# CRITICAL: All data mounts use bind mounts (~/path), NOT named volumes. +# This ensures the DB and theme are visible on the host filesystem for backup. services: prod: diff --git a/manage.sh b/manage.sh index 24fc84ff..1a30bad2 100755 --- a/manage.sh +++ b/manage.sh @@ -52,19 +52,12 @@ is_done() { [ -f "$STATE_FILE" ] && grep -qx "$1" "$STATE_FILE" 2>/dev/null; # ─── Helpers ────────────────────────────────────────────────────────────── # Determine the correct data volume/mount args for docker run. -# Detects existing host data directories and uses bind mounts if found. +# Always uses bind mounts to ~/meshcore-data so the DB is visible on the filesystem. get_data_mount_args() { - # Check for existing host data directories with a DB file - if [ -d "$HOME/meshcore-data" ] && [ -f "$HOME/meshcore-data/meshcore.db" ]; then - echo "-v $HOME/meshcore-data:/app/data" - return - fi - if [ -d "$(pwd)/data" ] && [ -f "$(pwd)/data/meshcore.db" ]; then - echo "-v $(pwd)/data:/app/data" - return - fi - # Default: Docker named volume - echo "-v ${DATA_VOLUME}:/app/data" + # Always use bind mount to $HOME/meshcore-data + # Create the directory if it doesn't exist + mkdir -p "$HOME/meshcore-data" + echo "-v $HOME/meshcore-data:/app/data" } # Determine the required port mappings from Caddyfile @@ -924,7 +917,8 @@ cmd_backup() { info "Backing up to ${BACKUP_DIR}/" # Database - DB_PATH=$(docker volume inspect "$DATA_VOLUME" --format '{{ .Mountpoint }}' 2>/dev/null)/meshcore.db + # Always use bind mount path + DB_PATH="$HOME/meshcore-data/meshcore.db" if [ -f "$DB_PATH" ]; then cp "$DB_PATH" "$BACKUP_DIR/meshcore.db" log "Database ($(du -h "$BACKUP_DIR/meshcore.db" | cut -f1))" @@ -948,7 +942,8 @@ cmd_backup() { fi # Theme - THEME_PATH=$(docker volume inspect "$DATA_VOLUME" --format '{{ .Mountpoint }}' 2>/dev/null)/theme.json + # Always use bind mount path + THEME_PATH="$HOME/meshcore-data/theme.json" if [ -f "$THEME_PATH" ]; then cp "$THEME_PATH" "$BACKUP_DIR/theme.json" log "theme.json" @@ -1024,12 +1019,10 @@ cmd_restore() { docker stop "$CONTAINER_NAME" 2>/dev/null || true # Restore database - DEST_DB=$(docker volume inspect "$DATA_VOLUME" --format '{{ .Mountpoint }}' 2>/dev/null)/meshcore.db - if [ -d "$(dirname "$DEST_DB")" ]; then - cp "$DB_FILE" "$DEST_DB" - else - docker cp "$DB_FILE" "${CONTAINER_NAME}:/app/data/meshcore.db" - fi + # Always use bind mount path + mkdir -p "$HOME/meshcore-data" + DEST_DB="$HOME/meshcore-data/meshcore.db" + cp "$DB_FILE" "$DEST_DB" log "Database restored" # Restore config if present @@ -1047,10 +1040,8 @@ cmd_restore() { # Restore theme if present if [ -n "$THEME_FILE" ] && [ -f "$THEME_FILE" ]; then - DEST_THEME=$(docker volume inspect "$DATA_VOLUME" --format '{{ .Mountpoint }}' 2>/dev/null)/theme.json - if [ -d "$(dirname "$DEST_THEME")" ]; then - cp "$THEME_FILE" "$DEST_THEME" - fi + DEST_THEME="$HOME/meshcore-data/theme.json" + cp "$THEME_FILE" "$DEST_THEME" log "theme.json restored" fi @@ -1098,7 +1089,7 @@ cmd_reset() { rm -f "$STATE_FILE" log "Reset complete. Run './manage.sh setup' to start over." - echo " Data volume preserved. To delete it: docker volume rm ${DATA_VOLUME}" + echo " Data directory: ~/meshcore-data (not removed)" } # ─── Help ─────────────────────────────────────────────────────────────────