#!/bin/bash # build-and-push-image.sh # Script per buildare l'immagine Docker degli orchestrator e pusharla su un registry privato # Uso: ./build-and-push-image.sh [registry_url] [image_name] [tag] [dockerfile_type] # Esempio: ./build-and-push-image.sh registry.example.com:5000 orchestrator-app latest distroless set -e # ==================== CONFIGURAZIONE ==================== # Directory del progetto (dove si trova il Dockerfile) PROJECT_DIR="/home/alex/devel/proxmox-ha-setup/vm1" # Parametri da riga di comando con valori di default REGISTRY_URL=${1:-"192.168.1.204:5000"} IMAGE_NAME=${2:-"orchestrator-app"} TAG=${3:-"latest"} DOCKERFILE_TYPE=${4:-"standard"} # Determina quale Dockerfile usare e quale tag if [[ "$DOCKERFILE_TYPE" == "distroless" ]]; then DOCKERFILE="Dockerfile.distroless" BUILD_TYPE="Distroless (Multi-stage)" # Se il tag è "latest", usa "distroless", altrimenti aggiungi suffisso "-distroless" if [[ "$TAG" == "latest" ]]; then ACTUAL_TAG="distroless" else ACTUAL_TAG="${TAG}-distroless" fi else DOCKERFILE="Dockerfile" BUILD_TYPE="Standard (python:3.12-slim)" ACTUAL_TAG="$TAG" fi # Nome completo dell'immagine FULL_IMAGE_NAME="${REGISTRY_URL}/${IMAGE_NAME}:${ACTUAL_TAG}" LOCAL_IMAGE_NAME="${IMAGE_NAME}:${ACTUAL_TAG}" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # ==================== FUNZIONI ==================== print_header() { echo -e "${BLUE}================================================${NC}" echo -e "${BLUE}$1${NC}" echo -e "${BLUE}================================================${NC}" } print_success() { echo -e "${GREEN}✓ $1${NC}"; } print_warning() { echo -e "${YELLOW}⚠ $1${NC}"; } print_error() { echo -e "${RED}✗ $1${NC}"; } print_info() { echo -e "${CYAN}ℹ $1${NC}"; } check_command() { if ! command -v $1 &> /dev/null; then print_error "$1 non trovato. Installalo prima di continuare." exit 1 fi } show_usage() { echo "Uso: $0 [registry_url] [image_name] [tag] [dockerfile_type]" echo "" echo "Parametri opzionali (valori di default):" echo " registry_url - URL del registry privato (default: 192.168.1.204:5000)" echo " image_name - Nome dell'immagine (default: orchestrator-app)" echo " tag - Tag dell'immagine (default: latest)" echo " dockerfile_type - Tipo di Dockerfile: 'standard' o 'distroless' (default: standard)" echo "" echo "Dockerfile Types:" echo " standard - Usa Dockerfile (python:3.12-slim, ~333MB)" echo " distroless - Usa Dockerfile.distroless (gcr.io/distroless, ~180MB, più sicuro)" echo "" echo "Tag automatici:" echo " standard + latest → orchestrator-app:latest" echo " distroless + latest → orchestrator-app:distroless" echo " standard + v1.0 → orchestrator-app:v1.0" echo " distroless + v1.0 → orchestrator-app:v1.0-distroless" echo "" echo "Esempi:" echo " $0 # → orchestrator-app:latest (standard)" echo " $0 192.168.1.204:5000 orchestrator-app latest distroless # → orchestrator-app:distroless" echo " $0 192.168.1.204:5000 orchestrator-app v1.0.0 standard # → orchestrator-app:v1.0.0" echo " $0 192.168.1.204:5000 orchestrator-app v1.0.0 distroless # → orchestrator-app:v1.0.0-distroless" echo "" } # ==================== VALIDAZIONE ==================== # Mostra help se richiesto if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then show_usage exit 0 fi # ==================== SCRIPT PRINCIPALE ==================== print_header "BUILD E PUSH IMMAGINE DOCKER" # Check prerequisites print_info "Verifica prerequisiti..." check_command "docker" print_success "Docker trovato" # Verifica che la directory del progetto esista if [ ! -d "$PROJECT_DIR" ]; then print_error "Directory del progetto non trovata: $PROJECT_DIR" exit 1 fi # Verifica che il Dockerfile richiesto esista if [ ! -f "$PROJECT_DIR/$DOCKERFILE" ]; then print_error "Dockerfile non trovato: $PROJECT_DIR/$DOCKERFILE" if [[ "$DOCKERFILE_TYPE" == "distroless" ]]; then print_warning "Il Dockerfile.distroless non esiste. Usa 'standard' o crea il file." fi exit 1 fi print_info "" print_info "Configurazione build:" print_info " Directory progetto: $PROJECT_DIR" print_info " Dockerfile: ${CYAN}$DOCKERFILE${NC}" print_info " Build type: ${CYAN}$BUILD_TYPE${NC}" print_info " Registry: $REGISTRY_URL" print_info " Nome immagine: $IMAGE_NAME" print_info " Tag richiesto: $TAG" print_info " Tag effettivo: ${CYAN}$ACTUAL_TAG${NC}" print_info " Nome completo: ${CYAN}$FULL_IMAGE_NAME${NC}" print_info "" # Conferma dall'utente read -p "Procedere con la build? (Y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Nn]$ ]]; then print_warning "Build annullata dall'utente" exit 0 fi # ==================== BUILD ==================== print_header "STEP 1: Build dell'immagine Docker" print_info "Inizio build dell'immagine..." print_info "Comando: docker build --no-cache -f $DOCKERFILE -t $LOCAL_IMAGE_NAME $PROJECT_DIR" echo "" # Build dell'immagine con Dockerfile specificato if docker build -f "$PROJECT_DIR/$DOCKERFILE" -t "$LOCAL_IMAGE_NAME" "$PROJECT_DIR"; then print_success "Build completata con successo" else print_error "Build fallita" exit 1 fi # Tag dell'immagine per il registry print_info "Tagging dell'immagine per il registry..." docker tag "$LOCAL_IMAGE_NAME" "$FULL_IMAGE_NAME" print_success "Immagine taggata: $FULL_IMAGE_NAME" # ==================== INFORMAZIONI IMMAGINE ==================== print_header "STEP 2: Informazioni immagine" # Mostra le informazioni sull'immagine IMAGE_SIZE=$(docker images "$LOCAL_IMAGE_NAME" --format "{{.Size}}") IMAGE_ID=$(docker images "$LOCAL_IMAGE_NAME" --format "{{.ID}}") print_info "ID Immagine: $IMAGE_ID" print_info "Dimensione: $IMAGE_SIZE" print_info "" # Mostra i layer dell'immagine (opzionale) print_info "Layer dell'immagine:" docker history "$LOCAL_IMAGE_NAME" --human --format "table {{.Size}}\t{{.CreatedBy}}" | head -10 # ==================== TEST OPZIONALE ==================== print_header "STEP 3: Test immagine (opzionale)" read -p "Vuoi testare l'immagine localmente prima del push? (y/N) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then print_info "Avvio container di test..." print_info "Premere Ctrl+C per interrompere il test" echo "" # Test con un comando semplice if docker run --rm "$LOCAL_IMAGE_NAME" python --version; then print_success "Test completato con successo" else print_warning "Test fallito - ma puoi comunque procedere con il push" fi echo "" fi # ==================== PUSH AL REGISTRY ==================== print_header "STEP 4: Push al registry" print_info "Verifica connessione al registry..." # Verifica se il registry è raggiungibile (solo per http/https) if [[ "$REGISTRY_URL" =~ ^(localhost|127\.0\.0\.1) ]]; then print_warning "Registry locale detectato - assicurati che sia in esecuzione" else print_info "Registry remoto: $REGISTRY_URL" fi read -p "Procedere con il push dell'immagine? (Y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Nn]$ ]]; then print_warning "Push annullato dall'utente" print_info "L'immagine locale è disponibile come: $LOCAL_IMAGE_NAME" exit 0 fi print_info "Push dell'immagine al registry..." echo "" # Push dell'immagine if docker push "$FULL_IMAGE_NAME"; then print_success "Push completato con successo!" else print_error "Push fallito" print_warning "Verifica che:" print_warning " 1. Il registry sia in esecuzione e raggiungibile" print_warning " 2. Hai eseguito 'docker login $REGISTRY_URL'" print_warning " 3. Il registry accetti connessioni insicure se necessario" exit 1 fi # ==================== PULIZIA OPZIONALE ==================== print_header "STEP 5: Pulizia (opzionale)" read -p "Vuoi rimuovere l'immagine locale dopo il push? (y/N) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then print_info "Rimozione immagine locale..." docker rmi "$LOCAL_IMAGE_NAME" "$FULL_IMAGE_NAME" 2>/dev/null || true print_success "Immagine locale rimossa" else print_info "Immagine locale mantenuta: $LOCAL_IMAGE_NAME" fi # ==================== RIEPILOGO ==================== print_header "BUILD E PUSH COMPLETATI! 🎉" print_info "" print_info "Riepilogo:" print_info " Tipo build: ${CYAN}$BUILD_TYPE${NC}" print_info " Dockerfile: ${CYAN}$DOCKERFILE${NC}" print_info " Immagine: ${GREEN}$FULL_IMAGE_NAME${NC}" print_info " Dimensione: $IMAGE_SIZE" print_info " Registry: $REGISTRY_URL" print_info "" # Messaggio specifico per il tipo di build if [[ "$DOCKERFILE_TYPE" == "distroless" ]]; then print_info "Note Distroless:" print_info " ✓ Immagine più piccola e sicura" print_info " ✓ Solo bytecode Python (.pyc)" print_info " ✓ Nessuna shell (debug solo tramite log)" print_info " ✓ Ideale per produzione" else print_info "Note Standard:" print_info " ✓ Include shell per debugging" print_info " ✓ Bytecode Python (.pyc)" print_info " ✓ Ideale per sviluppo e staging" fi print_info "" print_info "Per utilizzare l'immagine nei docker-compose.yml:" print_info " Sostituisci 'build: .' con:" print_info " ${CYAN}image: $FULL_IMAGE_NAME${NC}" print_info "" print_info "Per pullare l'immagine su un'altra macchina:" print_info " ${CYAN}docker pull $FULL_IMAGE_NAME${NC}" print_info "" print_success "Operazione completata con successo!"