#!/bin/bash # Docker Entrypoint Script for Trasabilitate Application # Handles initialization, health checks, and graceful startup set -e # Exit on error set -u # Exit on undefined variable set -o pipefail # Exit on pipe failure # ============================================================================ # LOGGING UTILITIES # ============================================================================ log_info() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] ℹ️ INFO: $*" } log_success() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] ✅ SUCCESS: $*" } log_warning() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] ⚠️ WARNING: $*" } log_error() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] ❌ ERROR: $*" >&2 } # ============================================================================ # ENVIRONMENT VALIDATION # ============================================================================ validate_environment() { log_info "Validating environment variables..." local required_vars=("DB_HOST" "DB_PORT" "DB_NAME" "DB_USER" "DB_PASSWORD") local missing_vars=() for var in "${required_vars[@]}"; do if [ -z "${!var:-}" ]; then missing_vars+=("$var") fi done if [ ${#missing_vars[@]} -gt 0 ]; then log_error "Missing required environment variables: ${missing_vars[*]}" exit 1 fi log_success "Environment variables validated" } # ============================================================================ # DATABASE CONNECTION CHECK # ============================================================================ wait_for_database() { local max_retries="${DB_MAX_RETRIES:-60}" local retry_interval="${DB_RETRY_INTERVAL:-2}" local retry_count=0 log_info "Waiting for MariaDB to be ready..." log_info "Database: ${DB_USER}@${DB_HOST}:${DB_PORT}/${DB_NAME}" while [ $retry_count -lt $max_retries ]; do if python3 << END import mariadb import sys try: conn = mariadb.connect( user="${DB_USER}", password="${DB_PASSWORD}", host="${DB_HOST}", port=int(${DB_PORT}), database="${DB_NAME}", connect_timeout=5 ) conn.close() sys.exit(0) except Exception as e: print(f"Connection failed: {e}") sys.exit(1) END then log_success "Database connection established!" return 0 fi retry_count=$((retry_count + 1)) log_warning "Database not ready (attempt ${retry_count}/${max_retries}). Retrying in ${retry_interval}s..." sleep $retry_interval done log_error "Failed to connect to database after ${max_retries} attempts" exit 1 } # ============================================================================ # DIRECTORY SETUP # ============================================================================ setup_directories() { log_info "Setting up application directories..." # Create necessary directories mkdir -p /app/instance mkdir -p /srv/quality_recticel/logs # Set proper permissions (if not running as root) if [ "$(id -u)" != "0" ]; then log_info "Running as non-root user (UID: $(id -u))" fi log_success "Directories configured" } # ============================================================================ # DATABASE CONFIGURATION # ============================================================================ create_database_config() { log_info "Creating database configuration file..." local config_file="/app/instance/external_server.conf" cat > "$config_file" << EOF # Database Configuration - Generated on $(date) server_domain=${DB_HOST} port=${DB_PORT} database_name=${DB_NAME} username=${DB_USER} password=${DB_PASSWORD} EOF # Secure the config file (contains password) chmod 600 "$config_file" log_success "Database configuration created at: $config_file" } # ============================================================================ # DATABASE INITIALIZATION # ============================================================================ initialize_database() { if [ "${INIT_DB:-false}" = "true" ]; then log_info "Initializing database schema..." if python3 /app/app/db_create_scripts/setup_complete_database.py; then log_success "Database schema initialized successfully" else local exit_code=$? if [ $exit_code -eq 0 ] || [ "${IGNORE_DB_INIT_ERRORS:-false}" = "true" ]; then log_warning "Database initialization completed with warnings (exit code: $exit_code)" else log_error "Database initialization failed (exit code: $exit_code)" exit 1 fi fi else log_info "Skipping database initialization (INIT_DB=${INIT_DB:-false})" fi } # ============================================================================ # DATABASE SEEDING # ============================================================================ seed_database() { if [ "${SEED_DB:-false}" = "true" ]; then log_info "Seeding database with initial data..." if python3 /app/seed.py; then log_success "Database seeded successfully" else local exit_code=$? if [ "${IGNORE_SEED_ERRORS:-false}" = "true" ]; then log_warning "Database seeding completed with warnings (exit code: $exit_code)" else log_error "Database seeding failed (exit code: $exit_code)" exit 1 fi fi else log_info "Skipping database seeding (SEED_DB=${SEED_DB:-false})" fi } # ============================================================================ # HEALTH CHECK # ============================================================================ run_health_check() { if [ "${SKIP_HEALTH_CHECK:-false}" = "true" ]; then log_info "Skipping pre-startup health check" return 0 fi log_info "Running application health checks..." # Check Python imports if ! python3 -c "import flask, mariadb, gunicorn" 2>/dev/null; then log_error "Required Python packages are not properly installed" exit 1 fi log_success "Health checks passed" } # ============================================================================ # SIGNAL HANDLERS FOR GRACEFUL SHUTDOWN # ============================================================================ setup_signal_handlers() { trap 'log_info "Received SIGTERM, shutting down gracefully..."; exit 0' SIGTERM trap 'log_info "Received SIGINT, shutting down gracefully..."; exit 0' SIGINT } # ============================================================================ # MAIN EXECUTION # ============================================================================ main() { echo "============================================================================" echo "🚀 Trasabilitate Application - Docker Container Startup" echo "============================================================================" echo " Container ID: $(hostname)" echo " Start Time: $(date)" echo " User: $(whoami) (UID: $(id -u))" echo "============================================================================" # Setup signal handlers setup_signal_handlers # Execute initialization steps validate_environment setup_directories wait_for_database create_database_config initialize_database seed_database run_health_check echo "============================================================================" log_success "Initialization complete! Starting application..." echo "============================================================================" echo "" # Execute the main command (CMD from Dockerfile) exec "$@" } # Run main function main "$@"