@@ -1093,31 +1093,48 @@ fi
10931093
10941094# Health check loop
10951095ai " Running health checks..."
1096- MAX_ATTEMPTS=30
1096+ MAX_ATTEMPTS=90 # 90 * 2s = 180s -- covers base compose start_period (60s) + image pull
10971097ALL_HEALTHY=true
10981098
1099- # Parallel arrays (Bash 3.2 compatible -- no associative arrays)
1099+ # Parallel arrays (Bash 3.2 compatible -- no associative arrays).
1100+ # HEALTH_CONTAINERS holds the Docker container name when a service runs in
1101+ # Docker; an empty string means the service is host-native (llama-server
1102+ # runs natively on macOS via Metal; OpenCode is a LaunchAgent). Docker
1103+ # services wait on `docker inspect ... .State.Health.Status == healthy`;
1104+ # host-native services fall back to an HTTP probe on 127.0.0.1.
11001105HEALTH_NAMES=(" LLM (llama-server)" " Chat UI (Open WebUI)" )
1101- HEALTH_URLS=(" http://localhost:8080/health" " http://localhost:3000" )
1102- $ENABLE_VOICE && HEALTH_NAMES+=(" Whisper (STT)" ) && HEALTH_URLS+=(" http://localhost:9000/health" )
1103- $ENABLE_WORKFLOWS && HEALTH_NAMES+=(" n8n (Workflows)" ) && HEALTH_URLS+=(" http://localhost:5678/healthz" )
1104- [[ -x " $OPENCODE_BIN " ]] && HEALTH_NAMES+=(" OpenCode (IDE)" ) && HEALTH_URLS+=(" http://localhost:${OPENCODE_PORT} " )
1106+ HEALTH_URLS=(" http://127.0.0.1:8080/health" " http://127.0.0.1:3000" )
1107+ HEALTH_CONTAINERS=(" " " dream-webui" )
1108+ $ENABLE_VOICE && HEALTH_NAMES+=(" Whisper (STT)" ) && HEALTH_URLS+=(" http://127.0.0.1:9000/health" ) && HEALTH_CONTAINERS+=(" dream-whisper" )
1109+ $ENABLE_WORKFLOWS && HEALTH_NAMES+=(" n8n (Workflows)" ) && HEALTH_URLS+=(" http://127.0.0.1:5678/healthz" ) && HEALTH_CONTAINERS+=(" dream-n8n" )
1110+ [[ -x " $OPENCODE_BIN " ]] && HEALTH_NAMES+=(" OpenCode (IDE)" ) && HEALTH_URLS+=(" http://127.0.0.1:${OPENCODE_PORT} " ) && HEALTH_CONTAINERS+=(" " )
11051111
11061112for (( idx= 0 ; idx< ${# HEALTH_NAMES[@]} ; idx++ )) ; do
11071113 NAME=" ${HEALTH_NAMES[$idx]} "
11081114 URL=" ${HEALTH_URLS[$idx]} "
1115+ CONTAINER=" ${HEALTH_CONTAINERS[$idx]} "
11091116 HEALTHY=false
11101117
11111118 for (( attempt= 1 ; attempt<= MAX_ATTEMPTS; attempt++ )) ; do
1112- HTTP_CODE=$( curl -s -o /dev/null -w " %{http_code}" " $URL " 2> /dev/null || echo " 000" )
1113- if [[ " $HTTP_CODE " -ge 200 ]] && [[ " $HTTP_CODE " -lt 400 ]]; then
1114- HEALTHY=true
1115- break
1116- fi
1117- # 401/403 means service is responding (auth-protected) -- treat as healthy
1118- if [[ " $HTTP_CODE " == " 401" ]] || [[ " $HTTP_CODE " == " 403" ]]; then
1119- HEALTHY=true
1120- break
1119+ if [[ -n " $CONTAINER " ]]; then
1120+ # Docker service -- wait for the container healthcheck to report healthy.
1121+ STATUS=$( docker inspect --format ' {{.State.Health.Status}}' " $CONTAINER " 2> /dev/null || echo " missing" )
1122+ if [[ " $STATUS " == " healthy" ]]; then
1123+ HEALTHY=true
1124+ break
1125+ fi
1126+ else
1127+ # Host-native service -- poll HTTP on 127.0.0.1.
1128+ HTTP_CODE=$( curl -s -o /dev/null -w " %{http_code}" " $URL " 2> /dev/null || echo " 000" )
1129+ if [[ " $HTTP_CODE " -ge 200 ]] && [[ " $HTTP_CODE " -lt 400 ]]; then
1130+ HEALTHY=true
1131+ break
1132+ fi
1133+ # 401/403 means service is responding (auth-protected) -- treat as healthy
1134+ if [[ " $HTTP_CODE " == " 401" ]] || [[ " $HTTP_CODE " == " 403" ]]; then
1135+ HEALTHY=true
1136+ break
1137+ fi
11211138 fi
11221139 if (( attempt <= 3 || attempt % 5 == 0 )) ; then
11231140 ai " Waiting for ${NAME} ... (${attempt} /${MAX_ATTEMPTS} )"
0 commit comments