diff --git a/scripts/app/install/app_install.sh b/scripts/app/install/app_install.sh index e15c182..e2a5d9f 100644 --- a/scripts/app/install/app_install.sh +++ b/scripts/app/install/app_install.sh @@ -160,6 +160,21 @@ installApp() dockerComposeUpdateAndStartApp "$app_name" install _appCallHook "${app_slug}_install_post_start" "$app_name" + # Reality gate: after `up`, the app MUST have at least one container + # (its compose project == the app dir name). An image-pull failure + # creates none, yet the deep compose call chain swallows that error — + # without this the app is recorded as installed+active with nothing + # running (the silent-fail seen when a low path-MTU black-holed pulls). + # ps -a (not just running) so a created-but-slow-to-start container + # still counts; only a total absence is treated as failure. + if declare -F dockerCommandRun >/dev/null 2>&1 \ + && ! dockerCommandRun "docker ps -a --filter label=com.docker.compose.project=$app_name --format '{{.Names}}' 2>/dev/null" 2>/dev/null | grep -q '[^[:space:]]'; then + isError "$app_name did not start — no container was created (usually the image failed to pull). NOT recording it as installed." + isNotice "Fix the cause (often image-registry connectivity / MTU), then re-run: libreportal app install $app_name" + eval "$app_slug=n" + return 1 + fi + ((menu_number++)) echo "" echo "---- $menu_number. Running post-install integrations." diff --git a/scripts/docker/app/compose/up_app.sh b/scripts/docker/app/compose/up_app.sh index e222b09..6436abd 100755 --- a/scripts/docker/app/compose/up_app.sh +++ b/scripts/docker/app/compose/up_app.sh @@ -122,12 +122,17 @@ dockerComposeUp() fi if [[ $CFG_DOCKER_INSTALL_TYPE == "rootless" ]]; then isNotice "Starting container for $app_name, this may take a while..." - local result; result=$(dockerCommandRunInstallUser "cd $containers_dir$app_name && COMPOSE_PROGRESS=plain docker compose $setup_compose up $_compose_quiet $_compose_build_flag -d"); _rc=$? - checkSuccess "Started container for $app_name" + local result; result=$(dockerCommandRunInstallUser "cd $containers_dir$app_name && COMPOSE_PROGRESS=plain docker compose $setup_compose up $_compose_quiet $_compose_build_flag -d") + _rc=$? + # Restore $? to the compose exit code — a bare `checkSuccess` + # after `_rc=$?` would read the assignment's 0 and always print + # success, hiding a failed `up -d` (e.g. an image pull EOF). + ( exit "$_rc" ); checkSuccess "Started container for $app_name" elif [[ $CFG_DOCKER_INSTALL_TYPE == "rooted" ]]; then isNotice "Starting container for $app_name, this may take a while..." - local result; result=$(cd "$containers_dir$app_name" && COMPOSE_PROGRESS=plain docker compose $setup_compose up $_compose_quiet $_compose_build_flag -d); _rc=$? - checkSuccess "Started container for $app_name" + local result; result=$(cd "$containers_dir$app_name" && COMPOSE_PROGRESS=plain docker compose $setup_compose up $_compose_quiet $_compose_build_flag -d) + _rc=$? + ( exit "$_rc" ); checkSuccess "Started container for $app_name" fi # Used for the CLI dockertype switcher. else