docker container auto backup

This quick short script can let you quickly and efficiently back up an entire server full of running containers.

docker container auto backup

Here is a small quick script that can automatically stop, backup and restart all your containers (for an entire server!)  This does it by the container serial, so it helps to take a screen shot of them from time to time.

  • It gracefully stops each container
  • Snapshots each container and builds a tar which is backed up to your local server
  • Restarts each container.

Alternately you can just have it 'cycle' power on all your containers as well, where you have slow leaks and need to restart your containers every so often. Please note under the current configuration it just cycles the power, you must set:

is_backing=1
#!/bin/bash

# Check for required argument
if [ $# -ne 1 ]; then
    echo "Usage: $0 user@remote-host"
    exit 1
fi

REMOTE="$1"
BACKUP_DIR="./docker_backups"  # Local directory for backups; create if needed
mkdir -p "$BACKUP_DIR"

# Retrieve list of running containers with ID and Name on remote
CONTAINER_LINES=$(ssh "$REMOTE" "docker ps --format '{{.ID}} {{.Names}}'")

printf "Container lines: ${CONTAINER_LINES}\n"


# Exit early if no running containers
if [ -z "$CONTAINER_LINES" ]; then
    echo "No running Docker containers found on $REMOTE."
    exit 0
fi

# Read lines into an array for iteration
mapfile -t CONTAINER_ARRAY <<< "$CONTAINER_LINES"

# Extract IDs as space-separated for starting later
CONTAINER_IDS=$(echo "$CONTAINER_LINES" | awk '{print $1}' | xargs)

# Stop each running container individually on remote
echo "Stopping containers on $REMOTE..."
for LINE in "${CONTAINER_ARRAY[@]}"; do
    printf "Stopping container id: ${LINE}\n"
    CONTAINER_ID=$(echo "$LINE" | awk '{print $1}')
    ssh "$REMOTE" "docker stop $CONTAINER_ID"
done

is_backing=0

if [ "$is_backing" -eq 1 ]; then
# Backup each container
 for LINE in "${CONTAINER_ARRAY[@]}"; do
    CONTAINER_ID=$(echo "$LINE" | awk '{print $1}')
    CONTAINER_NAME=$(echo "$LINE" | awk '{print $2}')
    echo "Backing up container $CONTAINER_NAME (ID: $CONTAINER_ID)..."

    # Commit container to a temporary image on remote, using name in tag
    IMAGE_NAME="backup_${CONTAINER_NAME}_$(date +%Y%m%d%H%M%S)"
    ssh "$REMOTE" "docker commit $CONTAINER_ID $IMAGE_NAME"

    # Save the image to a tar file on remote /tmp, using name
    TAR_FILE="${CONTAINER_NAME}_backup.tar"
    ssh "$REMOTE" "docker save $IMAGE_NAME -o /tmp/$TAR_FILE"

    # Transfer the tar file to local backup directory
    scp "$REMOTE:/tmp/$TAR_FILE" "$BACKUP_DIR/"

    # Clean up on remote: remove tar file and temporary image
    ssh "$REMOTE" "rm /tmp/$TAR_FILE"
    ssh "$REMOTE" "docker rmi $IMAGE_NAME"
 done
fi

# Restart the original containers on remote
echo "Restarting containers on $REMOTE..."
ssh "$REMOTE" "docker start $CONTAINER_IDS"

echo "Backup completed. Files are in $BACKUP_DIR."

Saving it to example backup_docker.sh you simply set the execution bit for it with:

chmod +x backup_docker.sh

Crontab Scheduling the Backup

Getting it to run once a week, and setting  it to the local time of the area servers:

To schedule the provided Bash script to execute automatically once per week at midnight in Chicago local time (Central Time, which corresponds to the America/Chicago time zone), you will need to configure a cron job on the system where the script resides. Cron jobs typically operate in the system's default time zone (often UTC), so it is essential to explicitly specify the desired time zone to ensure accurate execution.

Prerequisites

  • Ensure the script (e.g., saved as backup_docker.sh) is executable. If not, run the command chmod +x /path/to/backup_docker.sh in the terminal.
  • Confirm that the system has cron installed and the cron daemon is running (common on most Linux distributions).
  • Replace /path/to/backup_docker.sh in the examples below with the actual full path to your script.
  • Replace user@remote-host with the appropriate SSH target for your remote server.

Steps to Configure the Cron Job

Edit the Crontab File: Open the crontab editor for the current user by executing the following command in the terminal:

crontab -e

This will open the crontab file in your default text editor (e.g., vi or nano). If this is your first time editing crontab, the file may be empty.

Add the Time Zone and Cron Entry: Append the following lines to the crontab file to set the time zone and define the job. This example schedules the script to run every Sunday at midnight Chicago time (adjust the day of the week if needed by changing the last asterisk value: 0 for Sunday, 1 for Monday, etc.):

CRON_TZ=America/Chicago
0 0 * * 0 /path/to/backup_docker.sh user@remote-host
  • Explanation of the Cron Expression:
  • 0: Minute (0, for the start of the hour).
  • 0: Hour (0, for midnight).
  • *: Day of the month (any).
  • *: Month (any).
  • 0: Day of the week (0 for Sunday).
  • The CRON_TZ=America/Chicago line ensures the job interprets the schedule in Central Time, accounting for Daylight Saving Time adjustments where applicable.

Save and Exit the Editor: Save the changes and exit the editor. For vi, press Esc, then type :wq and Enter. For nano, press Ctrl+O, Enter, then Ctrl+X. The system will confirm the crontab installation.

Verify the Cron Job: To confirm the entry has been added, list the current crontab with:

crontab -l

This should display the lines you added.

Additional Considerations

Logging and Error Handling: Cron jobs redirect standard output and errors to email by default (if mail is configured). To log output explicitly, modify the cron entry as follows:

CRON_TZ=America/Chicago
0 0 * * 0 /path/to/backup_docker.sh user@remote-host >> /path/to/logfile.log 2>&1

This appends all output to a specified log file for review.

Time Zone Confirmation: If the system's default time zone differs, the CRON_TZ variable overrides it only for the subsequent jobs in the crontab. Verify the time zone by checking system settings or using the date command.

Testing: To test the setup without waiting a full week, temporarily adjust the cron expression to a near-future time (e.g., a few minutes from now) and monitor execution. Restore the original schedule afterward.

Potential Issues: If the cron job fails (e.g., due to permissions or SSH key issues), review system logs (typically in /var/log/syslog or /var/log/cron) for details. Ensure SSH access to the remote server is configured for non-interactive use.

This configuration will ensure the script runs reliably at the specified interval and time zone.

Linux Rocks Every Day