Files
dokku/plugins/scheduler-docker-local/check-deploy
Jose Diaz-Gonzalez 915172c0c5 fix: move proxy-port properties to proxy plugin and fix CI failures
- Move proxy-port and proxy-ssl-port properties from ports plugin to
  proxy plugin where they conceptually belong
- Generalize proxy:set to handle any property (matching ps:set pattern)
  instead of only handling the type property
- Fix apps:set --global flag parsing (pflag treats --global as a flag,
  not an argument — must be defined explicitly like ps:set does)
- Add missing property-functions source to scheduler-docker-local
  shell scripts (scheduler-enter, scheduler-run, scheduler-deploy,
  check-deploy, bin/scheduler-deploy-process-container)
- Update nginx-vhosts property references from ports to proxy plugin
- Update tests to use proxy:set for proxy-port properties
2026-04-25 17:19:42 -04:00

183 lines
7.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Hook to check server against list of checks specified in CHECKS file.
#
# The CHECKS file may contain empty lines, comments (lines starting with #),
# settings (NAME=VALUE) and check instructions.
#
# The format of a check instruction is a path, optionally followed by the
# expected content. For example:
#
# / My Amazing App
# /stylesheets/index.css .body
# /scripts/index.js $(function()
# /images/logo.png
#
# To check an application that supports multiple hostnames, use relative URLs
# that include the hostname, for example:
#
# //admin.example.com Admin Dashboard
# //static.example.com/logo.png
#
# You can also specify the protocol to explicitly check HTTPS requests.
#
# The default behavior is to wait for 5 seconds before running the first check,
# and timeout each check to 30 seconds.
#
# By default, checks will be retried 5 times.
# You can change these by setting WAIT, TIMEOUT and ATTEMPTS to different values, for
# example:
#
# WAIT=30 # Wait 1/2 minute
# TIMEOUT=60 # Timeout after a minute
# ATTEMPTS=10 # retry checks 10 times
#
set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions"
source "$PLUGIN_AVAILABLE_PATH/checks/functions"
source "$PLUGIN_AVAILABLE_PATH/config/functions"
source "$PLUGIN_AVAILABLE_PATH/scheduler-docker-local/internal-functions"
trigger-scheduler-docker-local-check-deploy() {
declare desc="scheduler-docker-local check-deploy plugin trigger"
declare trigger="check-deploy"
declare APP="$1" DOKKU_APP_CONTAINER_ID="$2" DOKKU_APP_CONTAINER_TYPE="$3" DOKKU_APP_LISTEN_PORT="$4" DOKKU_APP_LISTEN_IP="$5" CONTAINER_INDEX="$6"
local content
local DOKKU_SCHEDULER=$(get_app_scheduler "$APP")
if [[ "$DOKKU_SCHEDULER" != "docker-local" ]]; then
return
fi
if [[ -z "$DOKKU_APP_LISTEN_PORT" ]] && [[ -f "$DOKKU_ROOT/$APP/PORT" ]]; then
local DOKKU_APP_LISTEN_PORT=$(<"$DOKKU_ROOT/$APP/PORT")
fi
if [[ -z "$DOKKU_APP_CONTAINER_ID" ]]; then
local DOKKU_APP_CIDS=($(get_app_container_ids "$APP"))
local DOKKU_APP_CONTAINER_ID=${DOKKU_APP_CIDS[0]}
fi
if [[ "$(is_app_proctype_checks_skipped "$APP" "$DOKKU_APP_CONTAINER_TYPE")" == "true" ]]; then
dokku_log_info2_quiet "Zero downtime checks have been skipped ($DOKKU_APP_CONTAINER_TYPE.$CONTAINER_INDEX)"
exit 0
fi
# Wait this many seconds (default 5) for server to start before running checks.
local WAIT="$(fn-plugin-property-get-default "checks" "$APP" "wait" "5")"
# Wait this many seconds (default 30) for each response.
local TIMEOUT="$(fn-plugin-property-get-default "checks" "$APP" "timeout" "30")"
# use this number of retries for checks
local ATTEMPTS="$(fn-plugin-property-get-default "checks" "$APP" "attempts" "5")"
local CHECKS_FILENAME="$(fn-scheduler-docker-local-get-process-specific-checks-file-path "$APP")"
local IMAGE_TAG="$(get_running_image_tag "$APP")"
local IMAGE=$(get_deploying_app_image_name "$APP" "$IMAGE_TAG")
local TMP_APP_JSON_OUTPUT=$(mktemp "/tmp/dokku-${DOKKU_PID}-${FUNCNAME[0]}.XXXXXX")
trap "rm -rf '$TMP_APP_JSON_OUTPUT' >/dev/null" RETURN INT TERM EXIT
plugn trigger app-json-get-content "$APP" >"$TMP_APP_JSON_OUTPUT"
if [[ -s "${CHECKS_FILENAME}" ]]; then
# Reads name/value pairs, sets the WAIT and TIMEOUT variables
exec <"$CHECKS_FILENAME"
local line
local NAME
local VALUE
while read -r line; do
line=$(strip_inline_comments "$line")
# Name/value pair
if [[ "$line" =~ ^.+= ]]; then
NAME=${line%=*}
VALUE=${line#*=}
[[ "$NAME" == "WAIT" ]] && local WAIT=$VALUE
[[ "$NAME" == "TIMEOUT" ]] && local TIMEOUT=$VALUE
[[ "$NAME" == "ATTEMPTS" ]] && local ATTEMPTS=$VALUE
fi
done
dokku_log_warn "Deprecated: Usage of the CHECKS file is deprecated in favor of healthchecks in app.json"
dokku_log_warn "Please move your healthchecks to app.json."
content="$(docker-container-healthchecker convert "$CHECKS_FILENAME" --app-json "$TMP_APP_JSON_OUTPUT" --pretty)"
echo "$content" >"$TMP_APP_JSON_OUTPUT"
fi
checks_check_deploy_cleanup() {
declare desc="print container output"
declare APP="$1" DOKKU_APP_CONTAINER_TYPE="$2" CID="$3" CONTAINER_INDEX="$4" TMP_FILE="$5"
if [[ $CID ]]; then
dokku_log_info2_quiet "Start of $APP container output (${CID:0:12} $DOKKU_APP_CONTAINER_TYPE.$CONTAINER_INDEX)"
dokku_container_log_verbose_quiet "$CID"
dokku_log_info2_quiet "End of $APP container output (${CID:0:12} $DOKKU_APP_CONTAINER_TYPE.$CONTAINER_INDEX)"
fi
rm -rf "$TMP_FILE" >/dev/null
}
trap "checks_check_deploy_cleanup $APP $DOKKU_APP_CONTAINER_TYPE $DOKKU_APP_CONTAINER_ID $CONTAINER_INDEX $TMP_APP_JSON_OUTPUT" RETURN INT TERM EXIT
local DOKKU_DEFAULT_CHECKS_WAIT="$(fn-plugin-property-get-default "checks" "--global" "default-wait" "10")"
content="$(docker-container-healthchecker add "$DOKKU_APP_CONTAINER_TYPE" --app-json "$TMP_APP_JSON_OUTPUT" --if-empty --pretty --uptime "$DOKKU_DEFAULT_CHECKS_WAIT")"
echo "$content" >"$TMP_APP_JSON_OUTPUT"
local FAILEDCHECKS=0
local SSL="$DOKKU_ROOT/$APP/tls"
declare -a ARG_ARRAY
ARG_ARRAY+=("--app-json")
ARG_ARRAY+=("$TMP_APP_JSON_OUTPUT")
ARG_ARRAY+=("--process-type")
ARG_ARRAY+=("$DOKKU_APP_CONTAINER_TYPE")
if [[ -e "$SSL/server.crt" && -e "$SSL/server.key" ]]; then
ARG_ARRAY+=("--header")
ARG_ARRAY+=("X-Forwarded-Proto: https")
fi
if [[ -n "$DOKKU_APP_LISTEN_IP" ]]; then
ARG_ARRAY+=("--ip-address")
ARG_ARRAY+=("$DOKKU_APP_LISTEN_IP")
fi
if [[ -n "$DOKKU_APP_LISTEN_PORT" ]]; then
ARG_ARRAY+=("--port")
ARG_ARRAY+=("$DOKKU_APP_LISTEN_PORT")
fi
local app_vhosts="$(plugn trigger domains-list "$APP")"
if [[ -n "$app_vhosts" ]]; then
for app_vhost in $app_vhosts; do
if [[ "$app_vhost" == "localhost" ]] || [[ "$app_vhost" == '*' ]]; then
continue
fi
ARG_ARRAY+=("--header")
ARG_ARRAY+=("Host: $app_vhost")
break
done
fi
if [[ "$DOKKU_APP_CONTAINER_TYPE" == "web" ]]; then
content="$(docker-container-healthchecker add "$DOKKU_APP_CONTAINER_TYPE" --app-json "$TMP_APP_JSON_OUTPUT" --listening-check --name "port listening check" --port "$DOKKU_APP_LISTEN_PORT" --pretty --warn-only)"
echo "$content" >"$TMP_APP_JSON_OUTPUT"
fi
local docker_container_healthchecker_path
docker_container_healthchecker_path="$(command -v docker-container-healthchecker)"
sudo "$docker_container_healthchecker_path" check "$DOKKU_APP_CONTAINER_ID" "${ARG_ARRAY[@]}" || FAILEDCHECKS="$?"
if [[ $FAILEDCHECKS -gt 0 ]]; then
"$DOCKER_BIN" container update --restart=no "$DOKKU_APP_CONTAINER_ID" &>/dev/null || true
"$DOCKER_BIN" container stop "$DOKKU_APP_CONTAINER_ID" || true
dokku_log_warn "Could not start due to $FAILEDCHECKS failed checks ($DOKKU_APP_CONTAINER_TYPE.$CONTAINER_INDEX)"
return 1
fi
trap - EXIT
dokku_log_verbose "All checks successful ($DOKKU_APP_CONTAINER_TYPE.$CONTAINER_INDEX)"
}
trigger-scheduler-docker-local-check-deploy "$@"