Skip to main content

Podman backups?


Geoff Burke
Forum|alt.badge.img+22

Backup, Backup, Backup. That is our mantra. So what about Podman?

I use to scripts to backup my Podman containers that I will admit I wrote with the help of AI 😀 since my coding skills are not enviable.

podman-backup.sh 

#!/bin/bash

# Podman Container Backup Script
# This script creates application-aware backups of Podman containers
# Run this script before performing VM backups

# Set backup directory
BACKUP_DIR="${HOME}/podman_backups/$(date +%Y%m%d_%H%M%S)"
LOG_FILE="${BACKUP_DIR}/backup.log"
CONTAINER_INFO_DIR="${BACKUP_DIR}/container_info"
IMAGES_DIR="${BACKUP_DIR}/images"
VOLUMES_DIR="${BACKUP_DIR}/volumes"
CONFIG_DIR="${BACKUP_DIR}/config"

# Create backup directory structure
mkdir -p "${BACKUP_DIR}" "${CONTAINER_INFO_DIR}" "${IMAGES_DIR}" "${VOLUMES_DIR}" "${CONFIG_DIR}"

# Start logging
exec > >(tee -a "${LOG_FILE}") 2>&1
echo "Starting Podman container backup at $(date)"
echo "Backup location: ${BACKUP_DIR}"

# Check if running with sudo/root
if [ "$EUID" -ne 0 ]; then
  echo "⚠️ WARNING: Not running as root. Some volume backups may fail due to permission issues."
  echo "Consider running this script with sudo for full backup capabilities."
fi

# Function to check if commands succeed and log appropriately
check_status() {
    if [ $1 -eq 0 ]; then
        echo "✅ SUCCESS: $2"
    else
        echo "❌ ERROR: $2 failed with exit code $1"
    fi
}

# Get a list of all running containers
echo "Discovering running Podman containers..."
CONTAINERS=$(podman ps -q)
if [ -z "$CONTAINERS" ]; then
    echo "No running containers found."
else
    echo "Found $(echo "$CONTAINERS" | wc -l) running containers."
fi

# Save container information
echo "Saving container information..."
podman ps -a --format json > "${CONTAINER_INFO_DIR}/containers.json"
check_status $? "Saving container list"

# Process each container
for CONTAINER_ID in $CONTAINERS; do
    # Get container details
    CONTAINER_NAME=$(podman inspect --format '{{.Name}}' "$CONTAINER_ID" | sed 's/^\///')
    CONTAINER_IMAGE=$(podman inspect --format '{{.ImageName}}' "$CONTAINER_ID")

    echo "Processing container: $CONTAINER_NAME (ID: $CONTAINER_ID, Image: $CONTAINER_IMAGE)"

    # Save detailed container configuration
    podman inspect "$CONTAINER_ID" > "${CONTAINER_INFO_DIR}/${CONTAINER_NAME}_inspect.json"
    check_status $? "Saving container inspection for $CONTAINER_NAME"

    # Save container image
    IMAGE_FILE="${IMAGES_DIR}/${CONTAINER_NAME}.tar"
    echo "Saving image for container $CONTAINER_NAME to $IMAGE_FILE..."
    podman save -o "$IMAGE_FILE" "$CONTAINER_IMAGE"
    check_status $? "Saving image for $CONTAINER_NAME"

    # Check if container uses volumes
    VOLUMES=$(podman inspect --format '{{range .Mounts}}{{if eq .Type "volume"}}{{.Name}} {{end}}{{end}}' "$CONTAINER_ID")

    if [ -n "$VOLUMES" ]; then
        echo "Container $CONTAINER_NAME uses volumes: $VOLUMES"

        # Create directory for this container's volumes
        CONTAINER_VOLUMES_DIR="${VOLUMES_DIR}/${CONTAINER_NAME}"
        mkdir -p "$CONTAINER_VOLUMES_DIR"

        # Process each volume
        for VOLUME in $VOLUMES; do
            echo "Backing up volume: $VOLUME"

            # Get volume path
            VOLUME_PATH=$(podman volume inspect --format '{{.Mountpoint}}' "$VOLUME")

            if [ -n "$VOLUME_PATH" ]; then
                # Prepare for application-aware backup
                echo "Performing application-aware backup for container $CONTAINER_NAME..."

                # Check if this is a database container that needs special handling
                if podman exec "$CONTAINER_ID" which mysqldump &>/dev/null; then
                    echo "MySQL/MariaDB container detected, performing database dump..."
                    # You may need to modify this to include proper credentials
                    podman exec "$CONTAINER_ID" mysqldump --all-databases > "${CONTAINER_VOLUMES_DIR}/${VOLUME}_mysql_dump.sql"
                    check_status $? "MySQL dump for $CONTAINER_NAME"

                elif podman exec "$CONTAINER_ID" which pg_dumpall &>/dev/null; then
                    echo "PostgreSQL container detected, performing database dump..."
                    # You may need to modify this to include proper credentials
                    podman exec "$CONTAINER_ID" pg_dumpall -U postgres > "${CONTAINER_VOLUMES_DIR}/${VOLUME}_postgres_dump.sql"
                    check_status $? "PostgreSQL dump for $CONTAINER_NAME"

                elif podman exec "$CONTAINER_ID" which mongodump &>/dev/null; then
                    echo "MongoDB container detected, performing database dump..."
                    MONGO_DUMP_DIR="${CONTAINER_VOLUMES_DIR}/${VOLUME}_mongo_dump"
                    mkdir -p "$MONGO_DUMP_DIR"
                    podman exec "$CONTAINER_ID" mongodump --out=/tmp/mongodump
                    podman cp "$CONTAINER_ID:/tmp/mongodump" "$MONGO_DUMP_DIR"
                    check_status $? "MongoDB dump for $CONTAINER_NAME"
                fi

                # Backup the volume data - using a safer method to handle permissions
                echo "Backing up volume data from $VOLUME_PATH..."
                VOLUME_BACKUP="${CONTAINER_VOLUMES_DIR}/${VOLUME}.tar.gz"

                # Method 1: Try direct access first
                if [ -r "$VOLUME_PATH" ]; then
                    echo "Direct volume backup method..."
                    tar -czf "$VOLUME_BACKUP" -C "$(dirname "$VOLUME_PATH")" "$(basename "$VOLUME_PATH")" 2>/dev/null
                    TAR_STATUS=$?

                    if [ $TAR_STATUS -ne 0 ]; then
                        echo "Direct backup failed, trying alternative method..."
                        # Method 2: Try using podman container with volume mounted
                        echo "Creating temporary container to access volume data..."
                        TEMP_CONTAINER_ID=$(podman run -d --rm -v "$VOLUME:/backup_source" alpine:latest sleep 300)

                        if [ -n "$TEMP_CONTAINER_ID" ]; then
                            echo "Copying data from temporary container..."
                            podman cp "$TEMP_CONTAINER_ID:/backup_source" "$CONTAINER_VOLUMES_DIR/${VOLUME}_data"
                            CP_STATUS=$?
                            podman stop "$TEMP_CONTAINER_ID" >/dev/null

                            if [ $CP_STATUS -eq 0 ]; then
                                tar -czf "$VOLUME_BACKUP" -C "$CONTAINER_VOLUMES_DIR" "${VOLUME}_data"
                                TAR_STATUS=$?
                                rm -rf "$CONTAINER_VOLUMES_DIR/${VOLUME}_data"
                            else
                                TAR_STATUS=$CP_STATUS
                            fi
                        fi
                    fi

                    # Method 3: If all else fails, use a data dump approach for containers that support it
                    if [ $TAR_STATUS -ne 0 ]; then
                        echo "Volume backup failed. Creating data export backup instead..."
                        # Create a record of the volume path for reference
                        echo "Volume path: $VOLUME_PATH" > "${CONTAINER_VOLUMES_DIR}/${VOLUME}_info.txt"
                        echo "⚠️ WARNING: Could not back up volume data directly. Created metadata only."
                        echo "The VM backup should include this data if the volume is within the VM's filesystem."
                        TAR_STATUS=0  # Don't fail the script - we've recorded the metadata
                    fi
                else
                    echo "Volume path not directly readable. Creating metadata only."
                    echo "Volume path: $VOLUME_PATH" > "${CONTAINER_VOLUMES_DIR}/${VOLUME}_info.txt"
                    echo "⚠️ WARNING: Volume data not accessible. Created metadata only."
                    echo "The VM backup should include this data if the volume is within the VM's filesystem."
                    TAR_STATUS=0  # Don't fail the script - we've recorded the metadata
                fi

                check_status $TAR_STATUS "Volume backup for $VOLUME"
            else
                echo "❌ ERROR: Could not determine path for volume $VOLUME"
            fi
        done
    else
        echo "Container $CONTAINER_NAME does not use volumes."
    fi

    # Check for bind mounts
    BIND_MOUNTS=$(podman inspect --format '{{range .Mounts}}{{if eq .Type "bind"}}{{.Source}}:{{.Destination}} {{end}}{{end}}' "$CONTAINER_ID")

    if [ -n "$BIND_MOUNTS" ]; then
        echo "Container $CONTAINER_NAME uses bind mounts: $BIND_MOUNTS"
        echo "NOTE: Bind mounts are typically backed up by the VM backup. No separate backup created."

        # Save bind mount information
        echo "$BIND_MOUNTS" > "${CONTAINER_INFO_DIR}/${CONTAINER_NAME}_bind_mounts.txt"
    fi

    echo "Completed backup for container: $CONTAINER_NAME"
    echo "---------------------------------------------"
done

# Save Podman configuration - more robust approach
echo "Backing up Podman configuration..."
# Check common locations for Podman configuration
CONFIG_LOCATIONS=(
    "${HOME}/.config/containers"
    "/etc/containers"
    "/usr/share/containers"
    "/var/lib/containers"
)

# Flag to track if we found and backed up any config
CONFIG_BACKED_UP=false

# Try to back up each location
for CONFIG_LOC in "${CONFIG_LOCATIONS[@]}"; do
    if [ -d "$CONFIG_LOC" ]; then
        echo "Found Podman configuration at: $CONFIG_LOC"
        # Use rsync if available for better copying with permissions
        if command -v rsync >/dev/null 2>&1; then
            rsync -a "$CONFIG_LOC/" "${CONFIG_DIR}/$(basename "$CONFIG_LOC")/"
        else
            cp -r "$CONFIG_LOC" "${CONFIG_DIR}/"
        fi

        if [ $? -eq 0 ]; then
            echo "✅ SUCCESS: Backed up configuration from $CONFIG_LOC"
            CONFIG_BACKED_UP=true
        else
            echo "❌ ERROR: Failed to back up configuration from $CONFIG_LOC"
        fi
    fi
done

# Save Podman system info
echo "Saving Podman system information..."
podman info --format json > "${CONFIG_DIR}/podman_info.json"
check_status $? "Saving Podman system information"

# Also get storage configuration
echo "Saving Podman storage configuration..."
podman system df --format json > "${CONFIG_DIR}/podman_storage.json"
check_status $? "Saving Podman storage information"

if [ "$CONFIG_BACKED_UP" = false ]; then
    echo "⚠️ WARNING: Could not find Podman configuration directories to back up."
    echo "This is not fatal - your container and image backups should still be valid."
fi

# Compress the entire backup for easier transport
echo "Compressing final backup..."
cd "$(dirname "$BACKUP_DIR")"
tar -czf "${BACKUP_DIR}.tar.gz" "$(basename "$BACKUP_DIR")"
check_status $? "Final backup compression"

# Display backup summary
TOTAL_SIZE=$(du -sh "${BACKUP_DIR}" | cut -f1)
echo "Backup completed at $(date)"
echo "Backup directory: ${BACKUP_DIR}"
echo "Compressed backup: ${BACKUP_DIR}.tar.gz"
echo "Total backup size: ${TOTAL_SIZE}"
echo "Containers backed up: $(echo "$CONTAINERS" | wc -l)"

echo "You can now proceed with your VM backup."

For restores:

podman-restore.sh

#!/bin/bash

# Podman Container Restore Script
# This script restores Podman containers from a backup created by the backup script

# Default to using the latest backup if no path is provided
if [ -z "$1" ]; then
    LATEST_BACKUP=$(find "${HOME}/podman_backups" -name "*.tar.gz" -type f -printf "%T@ %p\n" | sort -nr | head -1 | cut -d' ' -f2-)
    if [ -z "$LATEST_BACKUP" ]; then
        echo "❌ ERROR: No backup found in ${HOME}/podman_backups"
        echo "Please specify the backup file path: ./podman-restore.sh /path/to/backup.tar.gz"
        exit 1
    fi
    BACKUP_ARCHIVE="$LATEST_BACKUP"
    echo "Using latest backup: $BACKUP_ARCHIVE"
else
    BACKUP_ARCHIVE="$1"
    if [ ! -f "$BACKUP_ARCHIVE" ]; then
        echo "❌ ERROR: Backup file not found: $BACKUP_ARCHIVE"
        exit 1
    fi
fi

# Create temporary directory for extraction
TEMP_DIR=$(mktemp -d)
echo "Extracting backup to: $TEMP_DIR"

# Extract the backup
tar -xzf "$BACKUP_ARCHIVE" -C "$TEMP_DIR"
if [ $? -ne 0 ]; then
    echo "❌ ERROR: Failed to extract backup archive"
    rm -rf "$TEMP_DIR"
    exit 1
fi

# Find the actual backup directory
BACKUP_DIR=$(find "$TEMP_DIR" -maxdepth 1 -type d | grep -v "^$TEMP_DIR$" | head -1)
if [ -z "$BACKUP_DIR" ]; then
    echo "❌ ERROR: Could not find backup directory in archive"
    rm -rf "$TEMP_DIR"
    exit 1
fi

echo "Using backup directory: $BACKUP_DIR"

# Setup locations
CONTAINER_INFO_DIR="$BACKUP_DIR/container_info"
IMAGES_DIR="$BACKUP_DIR/images"
VOLUMES_DIR="$BACKUP_DIR/volumes"
CONFIG_DIR="$BACKUP_DIR/config"
RESTORE_LOG="$(pwd)/podman_restore_$(date +%Y%m%d_%H%M%S).log"

# Start logging
exec > >(tee -a "$RESTORE_LOG") 2>&1
echo "Starting Podman container restore at $(date)"
echo "Using backup from: $BACKUP_ARCHIVE"

# Check if running with sudo/root
if [ "$EUID" -ne 0 ]; then
  echo "⚠️ WARNING: Not running as root. Some operations may fail due to permission issues."
  echo "Consider running this script with sudo for full restore capabilities."
fi

# Function to check command success and log
check_status() {
    if [ $1 -eq 0 ]; then
        echo "✅ SUCCESS: $2"
    else
        echo "❌ ERROR: $2 failed with exit code $1"
    fi
}

# Function to ask for confirmation
confirm() {
    read -p "$1 [y/N] " response
    case "$response" in
        [yY][eE][sS]|[yY])
            return 0
            ;;
        *)
            return 1
            ;;
    esac
}

# 1. Restore configuration if available
echo "Checking for Podman configuration in backup..."
if [ -d "$CONFIG_DIR" ]; then
    echo "Found configuration backup. Would you like to restore it?"
    if confirm "This may overwrite your current Podman configuration. Continue?"; then
        echo "Restoring Podman configuration..."
        # Try to restore to common locations
        for CONFIG_DIR_NAME in $(ls "$CONFIG_DIR"); do
            CONFIG_SOURCE="$CONFIG_DIR/$CONFIG_DIR_NAME"

            if [ "$CONFIG_DIR_NAME" = "containers" ] && [ -d "$HOME/.config" ]; then
                # Restore user configuration
                echo "Restoring user configuration to $HOME/.config/containers"
                mkdir -p "$HOME/.config/containers"
                cp -r "$CONFIG_SOURCE"/* "$HOME/.config/containers/"
                check_status $? "Restoring user Podman configuration"
            elif [ "$CONFIG_DIR_NAME" = "containers" ] && [ -d "/etc" ]; then
                # Restore system configuration if running as root
                if [ "$EUID" -eq 0 ]; then
                    echo "Restoring system configuration to /etc/containers"
                    mkdir -p "/etc/containers"
                    cp -r "$CONFIG_SOURCE"/* "/etc/containers/"
                    check_status $? "Restoring system Podman configuration"
                else
                    echo "⚠️ Skipping system configuration restore (/etc/containers) - requires root"
                fi
            fi
        done
    else
        echo "Skipping configuration restore."
    fi
else
    echo "No configuration backup found. Skipping configuration restore."
fi

# 2. Restore images
echo "Checking for container images in backup..."
IMAGE_FILES=$(find "$IMAGES_DIR" -type f -name "*.tar")
if [ -n "$IMAGE_FILES" ]; then
    echo "Found $(echo "$IMAGE_FILES" | wc -l) container images to restore."
    for IMAGE in $IMAGE_FILES; do
        IMAGE_NAME=$(basename "$IMAGE" .tar)
        echo "Restoring image: $IMAGE_NAME"
        podman load -i "$IMAGE"
        check_status $? "Restoring image $IMAGE_NAME"
    done
else
    echo "No container images found in backup."
fi

# 3. Restore volumes
echo "Checking for volume data in backup..."
if [ -d "$VOLUMES_DIR" ]; then
    CONTAINER_VOLUME_DIRS=$(find "$VOLUMES_DIR" -mindepth 1 -maxdepth 1 -type d)
    if [ -n "$CONTAINER_VOLUME_DIRS" ]; then
        echo "Found volume backups for $(echo "$CONTAINER_VOLUME_DIRS" | wc -l) containers."

        for CONTAINER_DIR in $CONTAINER_VOLUME_DIRS; do
            CONTAINER_NAME=$(basename "$CONTAINER_DIR")
            echo "Processing volumes for container: $CONTAINER_NAME"

            # Check for volume tarballs
            VOLUME_TARS=$(find "$CONTAINER_DIR" -name "*.tar.gz" ! -name "*_data.tar.gz")
            for VOLUME_TAR in $VOLUME_TARS; do
                VOLUME_NAME=$(basename "$VOLUME_TAR" .tar.gz)
                echo "Found volume backup: $VOLUME_NAME"

                # Check if this volume already exists
                if podman volume exists "$VOLUME_NAME" 2>/dev/null; then
                    echo "Volume $VOLUME_NAME already exists."
                    if confirm "Would you like to recreate and restore this volume?"; then
                        echo "Removing existing volume: $VOLUME_NAME"
                        podman volume rm "$VOLUME_NAME"
                        check_status $? "Removing existing volume $VOLUME_NAME"
                    else
                        echo "Skipping volume $VOLUME_NAME restore."
                        continue
                    fi
                fi

                # Create new volume
                echo "Creating volume: $VOLUME_NAME"
                podman volume create "$VOLUME_NAME"
                check_status $? "Creating volume $VOLUME_NAME"

                # Get the volume path
                VOLUME_PATH=$(podman volume inspect --format '{{.Mountpoint}}' "$VOLUME_NAME")
                if [ -z "$VOLUME_PATH" ]; then
                    echo "❌ ERROR: Could not determine path for volume $VOLUME_NAME"
                    continue
                fi

                # Extract volume data
                echo "Extracting data to volume: $VOLUME_NAME at $VOLUME_PATH"

                # Create a temporary container to restore volume data
                echo "Creating temporary container to restore volume data..."
                TEMP_EXTRACT_DIR="$TEMP_DIR/extract_$VOLUME_NAME"
                mkdir -p "$TEMP_EXTRACT_DIR"

                # Extract tarball to temp directory
                tar -xzf "$VOLUME_TAR" -C "$TEMP_EXTRACT_DIR"

                # Create a temporary container and copy data
                TEMP_CONTAINER_ID=$(podman run -d --rm -v "$VOLUME_NAME:/restore_target" alpine:latest sleep 300)
                if [ -n "$TEMP_CONTAINER_ID" ]; then
                    # Copy from our extracted directory to the container
                    echo "Copying data to volume via temporary container..."
                    find "$TEMP_EXTRACT_DIR" -mindepth 1 -maxdepth 1 | while read item; do
                        podman cp "$item" "$TEMP_CONTAINER_ID:/restore_target/"
                    done

                    # Cleanup
                    podman stop "$TEMP_CONTAINER_ID" >/dev/null
                    rm -rf "$TEMP_EXTRACT_DIR"
                    echo "✅ SUCCESS: Restored volume $VOLUME_NAME"
                else
                    echo "❌ ERROR: Failed to create temporary container for volume restore"
                fi
            done

            # Check for database dumps
            DB_DUMPS=$(find "$CONTAINER_DIR" -name "*_mysql_dump.sql" -o -name "*_postgres_dump.sql")
            if [ -n "$DB_DUMPS" ]; then
                echo "Found database dumps for container $CONTAINER_NAME"
                echo "NOTE: To restore these database dumps, you'll need to:"
                echo "1. Start your database container"
                echo "2. Import the dumps using the appropriate database client"
                echo "Database dump locations:"
                for DUMP in $DB_DUMPS; do
                    echo "- $DUMP"
                done
            fi

            # Check for MongoDB dumps
            MONGO_DUMPS=$(find "$CONTAINER_DIR" -name "*_mongo_dump" -type d)
            if [ -n "$MONGO_DUMPS" ]; then
                echo "Found MongoDB dumps for container $CONTAINER_NAME"
                echo "NOTE: To restore these MongoDB dumps, you'll need to:"
                echo "1. Start your MongoDB container"
                echo "2. Use mongorestore to import the data"
                echo "MongoDB dump locations:"
                for DUMP in $MONGO_DUMPS; do
                    echo "- $DUMP"
                done
            fi
        done
    else
        echo "No volume backups found."
    fi
else
    echo "No volume directory found in backup."
fi

# 4. Provide guidance on recreating containers
echo "Checking for container configuration data..."
if [ -f "$CONTAINER_INFO_DIR/containers.json" ]; then
    echo "Found container configuration data."
    echo "Creating container recreation script..."

    # Create a script to help recreate containers
    RECREATE_SCRIPT="$(pwd)/recreate_containers.sh"

    cat > "$RECREATE_SCRIPT" << 'EOF'
#!/bin/bash
# Container recreation script generated from backup

# Load containers.json file
CONTAINER_JSON="$1"
if [ ! -f "$CONTAINER_JSON" ]; then
    echo "Usage: $0 /path/to/containers.json"
    exit 1
fi

# Process each container from the JSON
cat "$CONTAINER_JSON" | jq -c '.[]' | while read -r container; do
    # Extract container info
    NAME=$(echo "$container" | jq -r '.Names[0]' | sed 's/^\///')
    IMAGE=$(echo "$container" | jq -r '.Image')
    CREATED=$(echo "$container" | jq -r '.Created')

    echo "Container: $NAME"
    echo "  Image: $IMAGE"
    echo "  Created: $CREATED"

    # Look for detailed inspect file
    INSPECT_FILE="$(dirname "$CONTAINER_JSON")/${NAME}_inspect.json"
    if [ -f "$INSPECT_FILE" ]; then
        echo "  Found detailed configuration"

        # Extract container creation command
        echo "  Generating podman create command..."

        # Start building the command
        CMD="podman create --name $NAME"

        # Add environment variables
        ENV_VARS=$(cat "$INSPECT_FILE" | jq -r '.[0].Config.Env[]' 2>/dev/null)
        if [ -n "$ENV_VARS" ]; then
            echo "$ENV_VARS" | while read -r env; do
                CMD="$CMD --env '$env'"
            done
        fi

        # Add port mappings
        PORTS=$(cat "$INSPECT_FILE" | jq -r '.[0].HostConfig.PortBindings | to_entries[] | "\(.key):\(.value[0].HostPort)"' 2>/dev/null)
        if [ -n "$PORTS" ]; then
            echo "$PORTS" | while read -r port; do
                if [ -n "$port" ] && [ "$port" != "null:null" ]; then
                    CMD="$CMD --publish $port"
                fi
            done
        fi

        # Add volumes
        VOLUMES=$(cat "$INSPECT_FILE" | jq -r '.[0].Mounts[] | if .Type == "volume" then "-v \(.Name):\(.Destination)" elif .Type == "bind" then "-v \(.Source):\(.Destination)" else empty end' 2>/dev/null)
        if [ -n "$VOLUMES" ]; then
            echo "$VOLUMES" | while read -r volume; do
                if [ -n "$volume" ]; then
                    CMD="$CMD $volume"
                fi
            done
        fi

        # Add restart policy
        RESTART=$(cat "$INSPECT_FILE" | jq -r '.[0].HostConfig.RestartPolicy.Name' 2>/dev/null)
        if [ -n "$RESTART" ] && [ "$RESTART" != "null" ]; then
            CMD="$CMD --restart=$RESTART"
        fi

        # Add network mode
        NETWORK=$(cat "$INSPECT_FILE" | jq -r '.[0].HostConfig.NetworkMode' 2>/dev/null)
        if [ -n "$NETWORK" ] && [ "$NETWORK" != "null" ] && [ "$NETWORK" != "default" ]; then
            CMD="$CMD --network=$NETWORK"
        fi

        # Add command and args
        COMMAND=$(cat "$INSPECT_FILE" | jq -r '.[0].Config.Cmd | if type == "array" then join(" ") else . end' 2>/dev/null)

        # Finalize command with image and command
        CMD="$CMD $IMAGE"
        if [ -n "$COMMAND" ] && [ "$COMMAND" != "null" ]; then
            CMD="$CMD $COMMAND"
        fi

        echo "$CMD" > "$(dirname "$CONTAINER_JSON")/recreate_${NAME}.sh"
        chmod +x "$(dirname "$CONTAINER_JSON")/recreate_${NAME}.sh"
        echo "  Created recreation script: $(dirname "$CONTAINER_JSON")/recreate_${NAME}.sh"
    else
        echo "  No detailed configuration found"
    fi

    echo ""
done

echo "Container recreation scripts have been generated."
echo "Review each script before running to ensure it matches your requirements."
echo "After creating containers, start them with 'podman start <container_name>'"
EOF

    chmod +x "$RECREATE_SCRIPT"

    # Run the recreation script
    echo "Generating container recreation scripts..."
    $RECREATE_SCRIPT "$CONTAINER_INFO_DIR/containers.json"

    echo ""
    echo "Container recreation scripts have been generated in: $CONTAINER_INFO_DIR"
    echo "To recreate a container:"
    echo "1. Review the script in $CONTAINER_INFO_DIR/recreate_<container_name>.sh"
    echo "2. Run the script to create the container"
    echo "3. Start the container with: podman start <container_name>"
    echo ""
    echo "For database containers, you may need to restore data from the dumps after starting."
else
    echo "No container configuration data found."
fi

# Cleanup
echo "Cleaning up temporary files..."
rm -rf "$TEMP_DIR"
check_status $? "Cleanup temp directory"

echo ""
echo "Podman restore completed at $(date)"
echo "Restore log: $RESTORE_LOG"
echo ""
echo "Restore process summary:"
echo "1. Images: Restored from $IMAGES_DIR"
echo "2. Volumes: Restored from $VOLUMES_DIR"
echo "3. Container recreation scripts: Generated in $CONTAINER_INFO_DIR"
echo ""
echo "Next steps:"
echo "1. Review and run the container recreation scripts"
echo "2. Restore database dumps if applicable"
echo "3. Start your containers"
echo ""
echo "Thank you for using the Podman Container Restore Script!"

The idea is to run the backup.sh script in a Veeam backup job as a pre-script so that if you are running and databases like mysql or mongo you would have application aware backups.

Still a work in progress so if anyone else has solutions please share.

1 comment

Chris.Childerhose
Forum|alt.badge.img+21

Damn those are some long scripts LOL.  Great to see these to help others with their backups.