mirror of
https://github.com/dockersrc/almalinux
synced 2025-09-18 03:57:49 -04:00
🗃️ Committing everything that changed 🗃️
rootfs/usr/local/bin/entrypoint.sh rootfs/usr/local/etc/docker/functions/entrypoint.sh
This commit is contained in:
@@ -93,7 +93,7 @@ DATABASE_DIR="" # set database dir
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Healthcheck variables
|
||||
HEALTH_ENABLED="yes" # enable healthcheck [yes/no]
|
||||
SERVICES_LIST="tini" # comma seperated list of processes for the healthcheck
|
||||
SERVICES_LIST="" # auto-detected from init.d scripts - can be overridden
|
||||
HEALTH_ENDPOINTS="" # url endpoints: [http://localhost/health,http://localhost/test]
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Update path var
|
||||
@@ -341,7 +341,14 @@ if [ "$ENTRYPOINT_FIRST_RUN" != "no" ]; then
|
||||
fi
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# if no pid assume container restart
|
||||
[ -f "$ENTRYPOINT_PID_FILE" ] && [ -f "/run/__start_init_scripts.pid" ] || START_SERVICES="yes"
|
||||
# if no pid assume container restart - clean stale files on restart
|
||||
if [ ! -f "$ENTRYPOINT_PID_FILE" ]; then
|
||||
START_SERVICES="yes"
|
||||
# Clean stale pid files from previous container runs
|
||||
rm -f /run/__start_init_scripts.pid /run/init.d/*.pid /run/*.pid
|
||||
elif [ ! -f "/run/__start_init_scripts.pid" ]; then
|
||||
START_SERVICES="yes"
|
||||
fi
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
[ "$ENTRYPOINT_MESSAGE" = "yes" ] && __printf_space "40" "Container ip address is:" "$CONTAINER_IP4_ADDRESS"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@@ -70,7 +70,108 @@ __clean_variables() {
|
||||
printf '%s' "$var" | grep -v '^$'
|
||||
}
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
__no_exit() { [ -f "/run/no_exit.pid" ] || exec bash -c "trap 'sleep 1;rm -Rf /run/*;/tmp/*;/data/logs/start.log;exit 0' TERM INT;(while true; do echo $$ >/run/no_exit.pid;tail -qf /data/logs/start.log 2>/dev/null||sleep 20; done) & wait"; }
|
||||
# Auto-detect services from init.d scripts
|
||||
__auto_detect_services() {
|
||||
local discovered_services="tini" # Always include tini as init
|
||||
local init_dir="/usr/local/etc/docker/init.d"
|
||||
|
||||
if [ -d "$init_dir" ]; then
|
||||
for script in "$init_dir"/*.sh; do
|
||||
if [ -f "$script" ]; then
|
||||
# Extract service name from filename (remove number prefix and .sh suffix)
|
||||
local service=$(basename "$script" | sed 's/^[0-9]*-//;s|\.sh$||g')
|
||||
discovered_services="$discovered_services,$service"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "$discovered_services"
|
||||
}
|
||||
|
||||
# Enhanced __no_exit function with service monitoring and proper failure handling
|
||||
__no_exit() {
|
||||
local monitor_services="${SERVICES_LIST:-$(__auto_detect_services)}"
|
||||
local check_interval="${SERVICE_CHECK_INTERVAL:-30}"
|
||||
local max_failures="${MAX_SERVICE_FAILURES:-3}"
|
||||
declare -A failure_counts
|
||||
|
||||
# Initialize failure counters
|
||||
IFS=',' read -ra services <<< "$monitor_services"
|
||||
for service in "${services[@]}"; do
|
||||
service="${service// /}" # trim whitespace
|
||||
[ -n "$service" ] && failure_counts["$service"]=0
|
||||
done
|
||||
|
||||
echo "🔍 Starting service supervisor - monitoring: $monitor_services"
|
||||
echo "⏰ Check interval: ${check_interval}s, Max failures: $max_failures per service"
|
||||
|
||||
# Set up trap to handle termination gracefully
|
||||
trap 'echo "🛑 Container terminating - cleaning up services"; kill $(jobs -p) 2>/dev/null; rm -f /run/*.pid /run/init.d/*.pid; exit 0' TERM INT EXIT
|
||||
|
||||
# Main supervision loop
|
||||
while true; do
|
||||
local failed_services=""
|
||||
local running_services=""
|
||||
local critical_failure=false
|
||||
|
||||
# Check each monitored service
|
||||
IFS=',' read -ra services <<< "$monitor_services"
|
||||
for service in "${services[@]}"; do
|
||||
service="${service// /}" # trim whitespace
|
||||
[ -z "$service" ] && continue
|
||||
|
||||
if __pgrep "$service" >/dev/null 2>&1; then
|
||||
running_services="$running_services $service"
|
||||
failure_counts["$service"]=0 # reset failure count on success
|
||||
else
|
||||
failed_services="$failed_services $service"
|
||||
failure_counts["$service"]=$((${failure_counts["$service"]:-0} + 1))
|
||||
|
||||
echo "⚠️ Service '$service' not running (failure ${failure_counts["$service"]}/$max_failures)"
|
||||
|
||||
# Check if we've exceeded max failures for this service
|
||||
if [ ${failure_counts["$service"]} -ge $max_failures ]; then
|
||||
echo "💥 Service '$service' failed $max_failures times - this is critical!"
|
||||
critical_failure=true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# If we have critical failures, terminate the container
|
||||
if [ "$critical_failure" = true ]; then
|
||||
echo "🚨 Critical service failure detected:"
|
||||
echo " 💀 Dead services: $failed_services"
|
||||
echo " ✅ Running services: $running_services"
|
||||
echo " 🔄 Container will terminate to allow restart by orchestrator"
|
||||
|
||||
# Write final status to log
|
||||
{
|
||||
echo "$(date): CRITICAL FAILURE - Container terminating"
|
||||
echo "Dead services: $failed_services"
|
||||
echo "Running services: $running_services"
|
||||
} >> "/data/logs/start.log"
|
||||
|
||||
# Terminate the container (PID 1 is the init process)
|
||||
kill -TERM 1
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Log status periodically (every 10 cycles = ~5 minutes with 30s interval)
|
||||
if [ $(($(date +%s) % 300)) -lt $check_interval ]; then
|
||||
echo "📊 Service status - Running:$running_services Failed:$failed_services"
|
||||
# Write to start.log for backward compatibility
|
||||
echo "$(date): Services running:$running_services failed:$failed_services" >> "/data/logs/start.log"
|
||||
fi
|
||||
|
||||
sleep "$check_interval"
|
||||
done &
|
||||
|
||||
# Keep the original behavior for log tailing (for compatibility)
|
||||
[ -f "/data/logs/start.log" ] && tail -f "/data/logs/start.log" >/dev/null 2>&1 &
|
||||
|
||||
# Wait for background processes
|
||||
wait
|
||||
}
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
__trim() {
|
||||
local var="${*//;/ }"
|
||||
@@ -642,46 +743,130 @@ __exec_command() {
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Setup the server init scripts
|
||||
__start_init_scripts() {
|
||||
set -e
|
||||
trap 'echo "❌ Fatal error in service startup - killing container"; rm -f /run/__start_init_scripts.pid; kill -TERM 1' ERR
|
||||
|
||||
[ "$1" = " " ] && shift 1
|
||||
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -o pipefail -x$DEBUGGER_OPTIONS || set -o pipefail
|
||||
local retPID=""
|
||||
|
||||
local basename=""
|
||||
local init_pids=""
|
||||
local retstatus="0"
|
||||
local initStatus="0"
|
||||
local failed_services=""
|
||||
local successful_services=""
|
||||
local init_dir="${1:-/usr/local/etc/docker/init.d}"
|
||||
local init_count="$(ls -A "$init_dir"/* 2>/dev/null | grep -v '\.sample' | wc -l)"
|
||||
touch /run/__start_init_scripts.pid
|
||||
mkdir -p "/tmp" "/run" "/run/init.d" "/usr/local/etc/docker/exec"
|
||||
chmod -R 777 "/tmp" "/run" "/run/init.d" "/usr/local/etc/docker/exec"
|
||||
local init_count="$(find "$init_dir" -name "*.sh" 2>/dev/null | wc -l)"
|
||||
|
||||
if [ -n "$SERVICE_DISABLED" ]; then
|
||||
echo "$SERVICE_DISABLED is disabled"
|
||||
unset SERVICE_DISABLED
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "🚀 Starting container services initialization"
|
||||
echo "📂 Init directory: $init_dir"
|
||||
echo "📊 Services to start: $init_count"
|
||||
|
||||
# Create a fresh PID file to track this startup session
|
||||
echo $$ > /run/__start_init_scripts.pid
|
||||
|
||||
mkdir -p "/tmp" "/run" "/run/init.d" "/usr/local/etc/docker/exec" "/data/logs/init"
|
||||
chmod -R 777 "/tmp" "/run" "/run/init.d" "/usr/local/etc/docker/exec" "/data/logs/init"
|
||||
|
||||
if [ "$init_count" -eq 0 ] || [ ! -d "$init_dir" ]; then
|
||||
mkdir -p "/data/logs/init"
|
||||
while :; do echo "Running: $(date)" >"/data/logs/init/keep_alive" && sleep 3600; done &
|
||||
echo "⚠️ No init scripts found in $init_dir"
|
||||
# Still create a minimal keep-alive for containers without services
|
||||
while true; do
|
||||
echo "$(date): No services - container keep-alive" >> "/data/logs/start.log"
|
||||
sleep 3600
|
||||
done &
|
||||
else
|
||||
echo "📋 Found $init_count service scripts to execute"
|
||||
|
||||
if [ -d "$init_dir" ]; then
|
||||
[ -f "$init_dir/service.sample" ] && __rm "$init_dir"/*.sample
|
||||
chmod -Rf 755 "$init_dir"/*.sh
|
||||
# Remove sample files
|
||||
find "$init_dir" -name "*.sample" -delete 2>/dev/null
|
||||
|
||||
# Make scripts executable
|
||||
find "$init_dir" -name "*.sh" -exec chmod 755 {} \; 2>/dev/null
|
||||
|
||||
# Execute scripts in numerical/alphabetical order
|
||||
for init in "$init_dir"/*.sh; do
|
||||
if [ -x "$init" ]; then
|
||||
name="$(basename "$init")"
|
||||
service="$(printf '%s' "$name" | sed 's/^[^-]*-//;s|.sh$||g')"
|
||||
printf '# - - - executing file: %s\n' "$init"
|
||||
eval "$init" && sleep 5 || sleep 3
|
||||
retPID=$(__get_pid "$service")
|
||||
if [ -n "$retPID" ]; then
|
||||
initStatus="0"
|
||||
printf '# - - - %s has been started - pid: %s\n' "$service" "${retPID:-error}"
|
||||
basename="$(basename "$init")"
|
||||
service="$(printf '%s' "$basename" | sed 's/^[0-9]*-//;s|\.sh$||g')"
|
||||
|
||||
printf '\n🔧 Executing service script: %s (service: %s)\n' "$init" "$service"
|
||||
|
||||
# Execute the init script and capture its exit code
|
||||
if eval "$init"; then
|
||||
sleep 5 # Give service more time to start properly
|
||||
|
||||
# Verify the service actually started by checking for PID
|
||||
retPID=$(__get_pid "$service")
|
||||
if [ -n "$retPID" ]; then
|
||||
initStatus="0"
|
||||
successful_services="$successful_services $service"
|
||||
printf '✅ Service %s started successfully - PID: %s\n' "$service" "$retPID"
|
||||
else
|
||||
# Service script succeeded but no PID found - this is suspicious
|
||||
initStatus="1"
|
||||
failed_services="$failed_services $service"
|
||||
printf '⚠️ Service %s script completed but no PID found\n' "$service"
|
||||
fi
|
||||
else
|
||||
initStatus="1"
|
||||
printf '# - - - %s has falied to start - check log %s\n' "$service" "docker log $CONTAINER_NAME"
|
||||
# Service script failed
|
||||
script_exit_code="$?"
|
||||
initStatus="1"
|
||||
failed_services="$failed_services $service"
|
||||
printf '❌ Init script %s failed with exit code %s\n' "$init" "$script_exit_code"
|
||||
fi
|
||||
echo ""
|
||||
else
|
||||
printf '⚠️ Script %s is not executable, skipping\n' "$init"
|
||||
fi
|
||||
|
||||
retstatus=$(($retstatus + $initStatus))
|
||||
printf '\n'
|
||||
done
|
||||
|
||||
printf '📊 Service startup summary:\n'
|
||||
printf ' ✅ Successful: %s\n' "${successful_services:-none}"
|
||||
printf ' ❌ Failed: %s\n' "${failed_services:-none}"
|
||||
printf ' 📈 Total status code: %s\n' "$retstatus"
|
||||
|
||||
# If any services failed to start, terminate the container immediately
|
||||
if [ $retstatus -gt 0 ]; then
|
||||
echo ""
|
||||
echo "💥 Service startup failures detected!"
|
||||
echo "🔄 Container will terminate to allow orchestrator restart"
|
||||
echo "📝 Check container logs for detailed failure information"
|
||||
|
||||
# Write failure information to log
|
||||
{
|
||||
echo "$(date): SERVICE STARTUP FAILURE"
|
||||
echo "Successful services: $successful_services"
|
||||
echo "Failed services: $failed_services"
|
||||
echo "Total errors: $retstatus"
|
||||
} >> "/data/logs/start.log"
|
||||
|
||||
# Clean up and exit
|
||||
rm -f /run/__start_init_scripts.pid
|
||||
exit $retstatus
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
printf '%s\n' "$SERVICE_NAME started on $(date)" >"/data/logs/start.log"
|
||||
|
||||
# Write successful startup status to log
|
||||
{
|
||||
echo "$(date): Container startup completed successfully"
|
||||
echo "Active services: $successful_services"
|
||||
[ -n "$failed_services" ] && echo "Failed services: $failed_services"
|
||||
echo "Status code: $retstatus"
|
||||
} >> "/data/logs/start.log"
|
||||
|
||||
printf '\n🎉 All services initialized successfully!\n'
|
||||
printf '🔍 Service monitoring will now begin...\n\n'
|
||||
return $retstatus
|
||||
}
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -1200,6 +1385,6 @@ export ENTRYPOINT_DATA_INIT_FILE DATA_DIR_INITIALIZED ENTRYPOINT_CONFIG_INIT_FIL
|
||||
export ENTRYPOINT_PID_FILE ENTRYPOINT_INIT_FILE ENTRYPOINT_FIRST_RUN
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# export the functions
|
||||
export -f __get_pid __start_init_scripts __is_running __certbot __update_ssl_certs __create_ssl_cert
|
||||
export -f __get_pid __start_init_scripts __is_running __certbot __update_ssl_certs __create_ssl_cert __no_exit __auto_detect_services
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# end of functions
|
||||
|
Reference in New Issue
Block a user