mirror of
https://github.com/dockersrc/alpine
synced 2025-09-17 21:57:43 -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
|
# Healthcheck variables
|
||||||
HEALTH_ENABLED="yes" # enable healthcheck [yes/no]
|
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]
|
HEALTH_ENDPOINTS="" # url endpoints: [http://localhost/health,http://localhost/test]
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# Update path var
|
# Update path var
|
||||||
@@ -341,7 +341,14 @@ if [ "$ENTRYPOINT_FIRST_RUN" != "no" ]; then
|
|||||||
fi
|
fi
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# if no pid assume container restart
|
# 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"
|
[ "$ENTRYPOINT_MESSAGE" = "yes" ] && __printf_space "40" "Container ip address is:" "$CONTAINER_IP4_ADDRESS"
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@@ -70,7 +70,108 @@ __clean_variables() {
|
|||||||
printf '%s' "$var" | grep -v '^$'
|
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() {
|
__trim() {
|
||||||
local var="${*//;/ }"
|
local var="${*//;/ }"
|
||||||
@@ -642,46 +743,130 @@ __exec_command() {
|
|||||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# Setup the server init scripts
|
# Setup the server init scripts
|
||||||
__start_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
|
[ "$1" = " " ] && shift 1
|
||||||
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -o pipefail -x$DEBUGGER_OPTIONS || set -o pipefail
|
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -o pipefail -x$DEBUGGER_OPTIONS || set -o pipefail
|
||||||
local retPID=""
|
|
||||||
local basename=""
|
local basename=""
|
||||||
local init_pids=""
|
local init_pids=""
|
||||||
local retstatus="0"
|
local retstatus="0"
|
||||||
local initStatus="0"
|
local initStatus="0"
|
||||||
|
local failed_services=""
|
||||||
|
local successful_services=""
|
||||||
local init_dir="${1:-/usr/local/etc/docker/init.d}"
|
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)"
|
local init_count="$(find "$init_dir" -name "*.sh" 2>/dev/null | wc -l)"
|
||||||
touch /run/__start_init_scripts.pid
|
|
||||||
mkdir -p "/tmp" "/run" "/run/init.d" "/usr/local/etc/docker/exec"
|
if [ -n "$SERVICE_DISABLED" ]; then
|
||||||
chmod -R 777 "/tmp" "/run" "/run/init.d" "/usr/local/etc/docker/exec"
|
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
|
if [ "$init_count" -eq 0 ] || [ ! -d "$init_dir" ]; then
|
||||||
mkdir -p "/data/logs/init"
|
echo "⚠️ No init scripts found in $init_dir"
|
||||||
while :; do echo "Running: $(date)" >"/data/logs/init/keep_alive" && sleep 3600; done &
|
# 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
|
else
|
||||||
|
echo "📋 Found $init_count service scripts to execute"
|
||||||
|
|
||||||
if [ -d "$init_dir" ]; then
|
if [ -d "$init_dir" ]; then
|
||||||
[ -f "$init_dir/service.sample" ] && __rm "$init_dir"/*.sample
|
# Remove sample files
|
||||||
chmod -Rf 755 "$init_dir"/*.sh
|
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
|
for init in "$init_dir"/*.sh; do
|
||||||
if [ -x "$init" ]; then
|
if [ -x "$init" ]; then
|
||||||
name="$(basename "$init")"
|
basename="$(basename "$init")"
|
||||||
service="$(printf '%s' "$name" | sed 's/^[^-]*-//;s|.sh$||g')"
|
service="$(printf '%s' "$basename" | sed 's/^[0-9]*-//;s|\.sh$||g')"
|
||||||
printf '# - - - executing file: %s\n' "$init"
|
|
||||||
eval "$init" && sleep 5 || sleep 3
|
printf '\n🔧 Executing service script: %s (service: %s)\n' "$init" "$service"
|
||||||
retPID=$(__get_pid "$service")
|
|
||||||
if [ -n "$retPID" ]; then
|
# Execute the init script and capture its exit code
|
||||||
initStatus="0"
|
if eval "$init"; then
|
||||||
printf '# - - - %s has been started - pid: %s\n' "$service" "${retPID:-error}"
|
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
|
else
|
||||||
initStatus="1"
|
# Service script failed
|
||||||
printf '# - - - %s has falied to start - check log %s\n' "$service" "docker log $CONTAINER_NAME"
|
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
|
fi
|
||||||
echo ""
|
else
|
||||||
|
printf '⚠️ Script %s is not executable, skipping\n' "$init"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
retstatus=$(($retstatus + $initStatus))
|
retstatus=$(($retstatus + $initStatus))
|
||||||
|
printf '\n'
|
||||||
done
|
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
|
||||||
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
|
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 ENTRYPOINT_PID_FILE ENTRYPOINT_INIT_FILE ENTRYPOINT_FIRST_RUN
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# export the functions
|
# 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
|
# end of functions
|
||||||
|
Reference in New Issue
Block a user