246 lines
7.9 KiB
Bash
Executable File
246 lines
7.9 KiB
Bash
Executable File
#!/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 "$@"
|