Files
proxmox-ha-setup/scripts/build-and-push-image.sh

290 lines
9.4 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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!"