Skip to main content

Creating a backup service container

1. Create a new container

This container should be a Linux-based container. The below docker-compose.yaml file is aa good example.

services:
  backup-container:
    image: ubuntu:22.04
    container_name: backupper
    command: sleep infinity
    ports:
      - '22:22'
    volumes:
      # Mount all your existing volumes here
      # Example format:
      # - volume_name:/backups/volume_name:ro
      - volume1:/backups/volume1:ro
      - volume2:/backups/volume2:ro
      # Add all volumes following this pattern

These volumes will be used to automate the backup process using a script.

Install Tools

Connect to the container and install the Azure CLI tools and nano

apt-get update
apt-get install -y curl apt-transport-https lsb-release gnupg nano

# Install Azure CLI
curl -sL https://aka.ms/InstallAzureCLIDeb | bash

2. Check the Mounts

Start up the container, connect to it, and check the volumes are correctly mounted to /backups/<name>

3. Add the backup Script

Create a new backup script, and paste the following content in:

#!/bin/bash

# Azure Storage Configuration
STORAGE_ACCOUNT="your-storage-account-name"
STORAGE_KEY="your-storage-account-key"
CONTAINER_NAME="backups"  # Azure blob container name
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

# Backup directory (where volumes are mounted)
BACKUP_DIR="/backups"
# The folder within the azure storage container 
CONTAINER_DIR="docker-backups"

# Parse command line arguments
SINGLE_VOLUME=""
if [ "$1" == "-v" ] || [ "$1" == "--volume" ]; then
    if [ -z "$2" ]; then
        echo "Error: Volume name required when using -v or --volume"
        echo "Usage: $0 [-v|--volume VOLUME_NAME]"
        echo "  Without arguments: backs up all volumes"
        echo "  With -v VOLUME_NAME: backs up only specified volume"
        exit 1
    fi
    SINGLE_VOLUME="$2"
fi

# Color output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

if [ -n "$SINGLE_VOLUME" ]; then
    echo -e "${GREEN}=== Backing Up Single Volume to Azure Blob Storage ===${NC}"
    echo "Volume: $SINGLE_VOLUME"
else
    echo -e "${GREEN}=== Starting Volume Backup to Azure Blob Storage ===${NC}"
fi
echo "Timestamp: $TIMESTAMP"
echo ""

# Check if Azure CLI is installed
if ! command -v az &> /dev/null; then
    echo -e "${RED}Azure CLI not found. Installing...${NC}"
    apt-get update && apt-get install -y curl apt-transport-https lsb-release gnupg
    curl -sL https://aka.ms/InstallAzureCLIDeb | bash
fi

# Create Azure blob container if it doesn't exist
echo -e "${YELLOW}Ensuring Azure container exists...${NC}"
az storage container create \
    --name "$CONTAINER_NAME" \
    --account-name "$STORAGE_ACCOUNT" \
    --account-key "$STORAGE_KEY" \
    --only-show-errors 2>/dev/null

# Navigate to backup directory
cd "$BACKUP_DIR" || exit 1

# If single volume specified, check if it exists
if [ -n "$SINGLE_VOLUME" ]; then
    if [ ! -d "$SINGLE_VOLUME" ]; then
        echo -e "${RED}Error: Volume '$SINGLE_VOLUME' not found in $BACKUP_DIR${NC}"
        echo ""
        echo "Available volumes:"
        ls -1d */ 2>/dev/null | sed 's|/||'
        exit 1
    fi
fi

# Check if there are any volumes to backup
if [ -z "$(ls -A)" ]; then
    echo -e "${RED}No volumes found in $BACKUP_DIR${NC}"
    exit 1
fi

# Track statistics
TOTAL_VOLUMES=0
SUCCESS_COUNT=0
FAILED_COUNT=0

# Backup each volume (or just the specified one)
for dir in */; do
    if [ -d "$dir" ]; then
        volume_name="${dir%/}"
        
        # Skip if single volume specified and this isn't it
        if [ -n "$SINGLE_VOLUME" ] && [ "$volume_name" != "$SINGLE_VOLUME" ]; then
            continue
        fi
        
        TOTAL_VOLUMES=$((TOTAL_VOLUMES + 1))
        archive_name="${volume_name}_${TIMESTAMP}.tar.gz"
        
        echo -e "${YELLOW}[$TOTAL_VOLUMES] Processing: $volume_name${NC}"
        
        # Create compressed archive
        echo "  Creating archive..."
        if tar -czf "$archive_name" "$volume_name" 2>/dev/null; then
            archive_size=$(du -h "$archive_name" | cut -f1)
            echo -e "  ${GREEN}✓${NC} Archive created: $archive_size"
            
            # Upload to Azure Blob Storage
            echo "  Uploading to Azure..."
            if az storage blob upload \
                --account-name "$STORAGE_ACCOUNT" \
                --account-key "$STORAGE_KEY" \
                --container-name "$CONTAINER_NAME" \
                --name "$CONTAINER_DIR/volumes/${archive_name}" \
                --file "$archive_name" \
                --only-show-errors \
                --output none 2>/dev/null; then
                
                echo -e "  ${GREEN}✓${NC} Upload successful"
                SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
                
                # Clean up local archive
                rm "$archive_name"
            else
                echo -e "  ${RED}✗${NC} Upload failed"
                FAILED_COUNT=$((FAILED_COUNT + 1))
                rm "$archive_name" 2>/dev/null
            fi
        else
            echo -e "  ${RED}✗${NC} Archive creation failed"
            FAILED_COUNT=$((FAILED_COUNT + 1))
        fi
        
        echo ""
    fi
done

# Summary
echo -e "${GREEN}=== Backup Complete ===${NC}"
echo "Total volumes: $TOTAL_VOLUMES"
echo -e "Successful: ${GREEN}$SUCCESS_COUNT${NC}"
if [ $FAILED_COUNT -gt 0 ]; then
    echo -e "Failed: ${RED}$FAILED_COUNT${NC}"
fi
echo ""
echo "Backups stored in Azure Blob Storage:"
echo "  Container: $CONTAINER_NAME"
echo "  Path: volumes/"
echo "  Format: {volume-name}_${TIMESTAMP}.tar.gz"

exit 0