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.