#!/bin/bash # Flat Scraper Deployment Script for Raspberry Pi # Usage: ./deploy.sh [options] set -e # Exit on any error # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Default values CLEANUP=true SKIP_BUILD=false SKIP_DEPLOY=false VERBOSE=false # Help function show_help() { echo "Flat Scraper Deployment Script" echo "" echo "Usage: $0 [options]" echo "" echo "Options:" echo " -h, --help Show this help message" echo " -c, --no-cleanup Skip image cleanup after build" echo " -b, --no-build Skip building new image" echo " -d, --no-deploy Skip docker-compose deployment" echo " -v, --verbose Verbose output" echo "" echo "Examples:" echo " $0 # Full deployment with cleanup" echo " $0 --no-cleanup # Deploy without cleanup" echo " $0 --no-build # Deploy existing image" echo "" } # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in -h|--help) show_help exit 0 ;; -c|--no-cleanup) CLEANUP=false shift ;; -b|--no-build) SKIP_BUILD=true shift ;; -d|--no-deploy) SKIP_DEPLOY=true shift ;; -v|--verbose) VERBOSE=true shift ;; *) echo -e "${RED}Unknown option: $1${NC}" show_help exit 1 ;; esac done # Logging functions log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # Check prerequisites check_prerequisites() { log_info "Checking prerequisites..." # Check if Docker is running if ! docker info >/dev/null 2>&1; then log_error "Docker is not running. Please start Docker first." exit 1 fi # Check if docker-compose is available if ! command -v docker-compose >/dev/null 2>&1; then # Try docker compose (without dash) - newer versions if ! docker compose version >/dev/null 2>&1; then log_error "Neither docker-compose nor docker compose is available." log_error "Please install Docker Compose first." exit 1 else log_info "Using 'docker compose' (newer syntax)" DOCKER_COMPOSE_CMD="docker compose" fi else log_info "Using 'docker-compose' (legacy syntax)" DOCKER_COMPOSE_CMD="docker-compose" fi # Check if .env file exists if [ ! -f ".env" ]; then log_error ".env file not found. Please create it from .env.example" exit 1 fi # Check disk space available_space=$(df . | tail -1 | awk '{print $4}') if [ "$available_space" -lt 1048576 ]; then # 1GB in KB log_warning "Low disk space detected: ${available_space}KB available" fi log_success "Prerequisites check passed" } # Show current status show_status() { log_info "Current Docker status:" echo "" # Show images log_info "Docker Images:" docker images | grep -E "(flat-scraper|REPOSITORY)" || echo "No flat-scraper images found" echo "" # Show containers log_info "Running Containers:" if command -v docker-compose >/dev/null 2>&1; then docker-compose ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | grep -E "(flat-scraper|CONTAINER)" || echo "No flat-scraper containers running" else docker compose ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | grep -E "(flat-scraper|CONTAINER)" || echo "No flat-scraper containers running" fi echo "" # Show storage usage log_info "Docker Storage Usage:" docker system df --format "table {{.Type}}\t{{.TotalCount}}\t{{.Size}}" echo "" } # Build Docker image build_image() { if [ "$SKIP_BUILD" = true ]; then log_info "Skipping build as requested" return fi log_info "Building Docker image..." # Build with verbose output if requested if [ "$VERBOSE" = true ]; then docker build --progress=plain -t flat-scraper . else docker build -t flat-scraper . fi # Check if build was successful if [ $? -eq 0 ]; then log_success "Docker image built successfully" # Show image size image_size=$(docker images flat-scraper:latest --format "{{.Size}}") log_info "Image size: $image_size" else log_error "Docker build failed" exit 1 fi } # Test the image test_image() { log_info "Testing Docker image..." # Quick test to see if image starts and Python works if docker run --rm flat-scraper python --version >/dev/null 2>&1; then log_success "Image test passed" else log_error "Image test failed" exit 1 fi } # Cleanup old images cleanup_images() { if [ "$CLEANUP" = false ]; then log_info "Skipping cleanup as requested" return fi log_info "Cleaning up old Docker images..." # Remove dangling images dangling_removed=$(docker image prune -f | grep "Total reclaimed space" | awk '{print $3}') # Remove all unused images (be more aggressive) if [ "$VERBOSE" = true ]; then log_info "Removing all unused images..." unused_removed=$(docker image prune -a -f | grep "Total reclaimed space" | awk '{print $3}' || echo "0B") fi log_success "Cleanup completed" if [ -n "$dangling_removed" ]; then log_info "Reclaimed space: $dangling_removed" fi } # Deploy with docker-compose deploy_services() { if [ "$SKIP_DEPLOY" = true ]; then log_info "Skipping deployment as requested" return fi log_info "Deploying services with docker-compose..." # Stop existing services if [ "$VERBOSE" = true ]; then log_info "Stopping existing services..." $DOCKER_COMPOSE_CMD down fi # Start services if [ "$VERBOSE" = true ]; then $DOCKER_COMPOSE_CMD up -d --build else $DOCKER_COMPOSE_CMD up -d fi # Check if services started successfully sleep 5 # Give services time to start running_containers=$($DOCKER_COMPOSE_CMD ps | grep "Up" | wc -l) total_containers=$($DOCKER_COMPOSE_CMD ps | grep -c "flat-scraper") if [ "$running_containers" -eq "$total_containers" ] && [ "$total_containers" -gt 0 ]; then log_success "All services deployed successfully" log_info "Running containers: $running_containers/$total_containers" else log_error "Some services failed to start" $DOCKER_COMPOSE_CMD ps exit 1 fi } # Show final status show_final_status() { log_info "Final deployment status:" echo "" # Show running containers log_info "Running services:" $DOCKER_COMPOSE_CMD ps echo "" # Show recent logs log_info "Recent logs (last 10 lines):" $DOCKER_COMPOSE_CMD logs --tail=10 echo "" # Show storage usage log_info "Final storage usage:" docker system df --format "table {{.Type}}\t{{.TotalCount}}\t{{.Size}}" echo "" log_success "Deployment completed successfully!" log_info "Your Flat Scraper is now running and will check every 6 hours." } # Main execution main() { echo -e "${BLUE}========================================${NC}" echo -e "${BLUE} Flat Scraper Deployment Script ${NC}" echo -e "${BLUE}========================================${NC}" echo "" # Show initial status show_status # Run deployment steps check_prerequisites build_image test_image cleanup_images deploy_services show_final_status echo "" log_success "🎉 Flat Scraper deployment completed!" echo "" log_info "Useful commands:" echo " $DOCKER_COMPOSE_CMD logs -f # Follow logs" echo " $DOCKER_COMPOSE_CMD ps # Check status" echo " $DOCKER_COMPOSE_CMD restart # Restart services" echo " $DOCKER_COMPOSE_CMD down # Stop services" echo " ./deploy.sh --no-build --no-cleanup # Quick restart" echo "" } # Run main function main "$@"