#!/bin/bash # Deployment Script für Synology NAS # Dieses Script wird auf der Synology NAS ausgeführt set -e # Exit on error # ============================================ # Configuration # ============================================ PROJECT_DIR="/volume1/docker/laravel-app" DOCKER_IMAGE="laravel-app" COMPOSE_FILE="docker-compose.synology.yml" ENV_FILE=".env.synology" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # ============================================ # Helper Functions # ============================================ log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # ============================================ # Pre-deployment Checks # ============================================ log_info "Starting deployment process..." # Check if running on Synology if [ ! -d "/volume1" ]; then log_error "This script should be run on Synology NAS" exit 1 fi # Navigate to project directory cd "$PROJECT_DIR" || { log_error "Project directory not found: $PROJECT_DIR" exit 1 } # Check if Docker is installed if ! command -v docker &> /dev/null; then log_error "Docker is not installed" exit 1 fi # Check if docker-compose is installed if ! command -v docker-compose &> /dev/null; then log_error "docker-compose is not installed" exit 1 fi # ============================================ # Load Docker Image # ============================================ if [ -f "laravel-app.tar.gz" ]; then log_info "Loading Docker image from artifact..." gunzip -c laravel-app.tar.gz | docker load # Tag the image appropriately LOADED_IMAGE=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep laravel-app | head -n1) if [ -n "$LOADED_IMAGE" ]; then docker tag "$LOADED_IMAGE" "${DOCKER_IMAGE}:latest" log_info "Tagged image as ${DOCKER_IMAGE}:latest" fi else log_warn "No Docker image artifact found. Using existing image or building..." # Check if Dockerfile exists and build if necessary if [ -f "Dockerfile" ]; then log_info "Building Docker image..." docker build -t "${DOCKER_IMAGE}:latest" . else log_error "Neither Docker artifact nor Dockerfile found" exit 1 fi fi # ============================================ # Environment Configuration # ============================================ if [ ! -f "$ENV_FILE" ]; then log_warn "Environment file not found: $ENV_FILE" if [ -f ".env.synology.example" ]; then log_info "Copying from .env.synology.example..." cp .env.synology.example "$ENV_FILE" log_warn "⚠️ Please configure $ENV_FILE with your settings!" else log_error "No environment configuration found" exit 1 fi fi # ============================================ # Backup Current Deployment # ============================================ log_info "Creating backup of current deployment..." BACKUP_DIR="/volume1/docker/backups/laravel-app" mkdir -p "$BACKUP_DIR" TIMESTAMP=$(date +%Y%m%d_%H%M%S) BACKUP_FILE="$BACKUP_DIR/backup_${TIMESTAMP}.tar.gz" # Backup database if container is running if docker ps --format '{{.Names}}' | grep -q "laravel_postgres"; then log_info "Backing up PostgreSQL database..." docker exec laravel_postgres pg_dump -U ingest_user ingest_db > "$BACKUP_DIR/db_${TIMESTAMP}.sql" fi # Keep only last 5 backups log_info "Cleaning old backups (keeping last 5)..." ls -t "$BACKUP_DIR"/db_*.sql 2>/dev/null | tail -n +6 | xargs -r rm # ============================================ # Stop Current Containers # ============================================ log_info "Stopping current containers..." if [ -f "$COMPOSE_FILE" ]; then docker-compose -f "$COMPOSE_FILE" down || log_warn "No containers to stop" else log_warn "Compose file not found: $COMPOSE_FILE" fi # ============================================ # Clean up old images (optional) # ============================================ log_info "Cleaning up old Docker images..." docker image prune -f # ============================================ # Start New Deployment # ============================================ log_info "Starting new deployment..." if [ ! -f "$COMPOSE_FILE" ]; then log_error "Docker Compose file not found: $COMPOSE_FILE" exit 1 fi # Pull/use latest images and start services docker-compose -f "$COMPOSE_FILE" up -d --build # ============================================ # Wait for Services to Start # ============================================ log_info "Waiting for services to start..." sleep 10 # Check if containers are running if ! docker ps --format '{{.Names}}' | grep -q "laravel_app"; then log_error "Laravel app container failed to start" # Show logs log_info "Container logs:" docker-compose -f "$COMPOSE_FILE" logs --tail=50 # Rollback log_warn "Attempting rollback..." docker-compose -f "$COMPOSE_FILE" down exit 1 fi # ============================================ # Post-deployment Tasks # ============================================ log_info "Running post-deployment tasks..." # Wait for database to be ready log_info "Waiting for database to be ready..." sleep 5 # Run migrations log_info "Running database migrations..." docker exec laravel_app php artisan migrate --force || log_warn "Migrations failed" # Clear caches log_info "Clearing caches..." docker exec laravel_app php artisan cache:clear || log_warn "Cache clear failed" docker exec laravel_app php artisan config:clear || log_warn "Config clear failed" docker exec laravel_app php artisan view:clear || log_warn "View clear failed" # Optimize log_info "Optimizing application..." docker exec laravel_app php artisan config:cache || log_warn "Config cache failed" docker exec laravel_app php artisan route:cache || log_warn "Route cache failed" docker exec laravel_app php artisan view:cache || log_warn "View cache failed" # ============================================ # Health Check # ============================================ log_info "Performing health check..." MAX_RETRIES=30 RETRY_COUNT=0 HEALTH_CHECK_URL="http://localhost:8080" while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do if curl -f -s "$HEALTH_CHECK_URL" > /dev/null 2>&1; then log_info "✅ Application is healthy!" break fi log_info "⏳ Waiting for application... ($RETRY_COUNT/$MAX_RETRIES)" sleep 5 RETRY_COUNT=$((RETRY_COUNT + 1)) done if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then log_error "Health check failed after $MAX_RETRIES attempts" # Show recent logs log_info "Recent application logs:" docker-compose -f "$COMPOSE_FILE" logs --tail=100 exit 1 fi # ============================================ # Display Status # ============================================ log_info "Deployment completed successfully! 🚀" log_info "Container status:" docker-compose -f "$COMPOSE_FILE" ps log_info "" log_info "===================================" log_info "Application URL: http://$(hostname -I | awk '{print $1}'):8080" log_info "===================================" log_info "" log_info "Useful commands:" log_info " - View logs: docker-compose -f $COMPOSE_FILE logs -f" log_info " - Restart: docker-compose -f $COMPOSE_FILE restart" log_info " - Stop: docker-compose -f $COMPOSE_FILE down" log_info " - Shell access: docker exec -it laravel_app sh" # ============================================ # Cleanup # ============================================ log_info "Cleaning up deployment artifacts..." rm -f laravel-app.tar.gz log_info "Deployment script completed!" exit 0