#!/bin/bash set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color echo -e "${GREEN}Photo Sharing Platform Backup Script${NC}" echo "====================================" # Configuration BACKUP_DIR="/opt/photo-sharing/backup" STACK_NAME="photo-sharing" RETENTION_DAYS=30 TIMESTAMP=$(date +%Y%m%d-%H%M%S) BACKUP_NAME="backup-${TIMESTAMP}" # Create backup directory mkdir -p $BACKUP_DIR/$BACKUP_NAME # Function to check if service is running check_service() { local service=$1 if docker service ps ${STACK_NAME}_${service} --format "{{.CurrentState}}" | grep -q "Running"; then return 0 else return 1 fi } # Backup database echo -e "${GREEN}Backing up database...${NC}" if check_service "db"; then DB_CONTAINER=$(docker ps -q -f name=${STACK_NAME}_db -f status=running | head -1) if [ ! -z "$DB_CONTAINER" ]; then docker exec $DB_CONTAINER pg_dumpall -U postgres > $BACKUP_DIR/$BACKUP_NAME/database.sql echo -e "${GREEN}Database backup completed${NC}" else echo -e "${RED}Database container not found${NC}" fi else echo -e "${YELLOW}Database service not running, skipping...${NC}" fi # Backup photos echo -e "${GREEN}Backing up photos...${NC}" if [ -d "/opt/photo-sharing/storage" ]; then tar -czf $BACKUP_DIR/$BACKUP_NAME/photos.tar.gz -C /opt/photo-sharing storage/ echo -e "${GREEN}Photos backup completed${NC}" else echo -e "${YELLOW}Photos directory not found, skipping...${NC}" fi # Backup application data echo -e "${GREEN}Backing up application data...${NC}" if [ -d "/opt/photo-sharing/data" ]; then tar -czf $BACKUP_DIR/$BACKUP_NAME/app-data.tar.gz -C /opt/photo-sharing data/ echo -e "${GREEN}Application data backup completed${NC}" else echo -e "${YELLOW}Application data directory not found, skipping...${NC}" fi # Backup Docker volumes echo -e "${GREEN}Backing up Docker volumes...${NC}" for volume in $(docker volume ls -q | grep ${STACK_NAME}); do echo "Backing up volume: $volume" docker run --rm \ -v $volume:/data \ -v $BACKUP_DIR/$BACKUP_NAME:/backup \ alpine tar -czf /backup/volume-${volume}.tar.gz -C /data . done # Backup configurations echo -e "${GREEN}Backing up configurations...${NC}" if [ -f "../../.env.production" ]; then cp ../../.env.production $BACKUP_DIR/$BACKUP_NAME/ fi # Export Docker secrets (encrypted) echo -e "${GREEN}Exporting Docker secrets info...${NC}" docker secret ls --filter "label=com.docker.stack.namespace=$STACK_NAME" > $BACKUP_DIR/$BACKUP_NAME/secrets-list.txt # Create backup manifest echo -e "${GREEN}Creating backup manifest...${NC}" cat > $BACKUP_DIR/$BACKUP_NAME/manifest.json << EOF { "timestamp": "$TIMESTAMP", "stack_name": "$STACK_NAME", "hostname": "$(hostname)", "docker_version": "$(docker version --format '{{.Server.Version}}')", "services": $(docker service ls --filter "label=com.docker.stack.namespace=$STACK_NAME" --format '{{json .}}' | jq -s .), "backup_contents": [ "database.sql", "photos.tar.gz", "app-data.tar.gz", "volume-*.tar.gz", ".env.production", "secrets-list.txt" ] } EOF # Compress entire backup echo -e "${GREEN}Compressing backup...${NC}" cd $BACKUP_DIR tar -czf ${BACKUP_NAME}.tar.gz $BACKUP_NAME/ rm -rf $BACKUP_NAME/ # Upload to S3 (optional) if [ ! -z "$S3_BACKUP_BUCKET" ] && command -v aws &> /dev/null; then echo -e "${GREEN}Uploading to S3...${NC}" aws s3 cp ${BACKUP_NAME}.tar.gz s3://${S3_BACKUP_BUCKET}/photo-sharing/ fi # Clean up old backups echo -e "${GREEN}Cleaning up old backups...${NC}" find $BACKUP_DIR -name "backup-*.tar.gz" -mtime +$RETENTION_DAYS -delete # Show backup summary BACKUP_SIZE=$(du -h $BACKUP_DIR/${BACKUP_NAME}.tar.gz | cut -f1) echo "" echo -e "${GREEN}Backup completed successfully!${NC}" echo -e "Backup file: $BACKUP_DIR/${BACKUP_NAME}.tar.gz" echo -e "Backup size: $BACKUP_SIZE" echo -e "Retention: $RETENTION_DAYS days" # Verify backup echo "" echo -e "${GREEN}Verifying backup...${NC}" tar -tzf $BACKUP_DIR/${BACKUP_NAME}.tar.gz | head -10 echo "..." echo -e "${GREEN}Backup verification complete${NC}"