Emitting the restart policy as a `--restart` argument from a `docker-args-process-deploy` trigger exposed a latent gluing bug: proxy and builder triggers concatenated `$STDIN$output` with no separator, and the scheduler and builders appended `docker-args-process-*` output directly onto the older `docker-args-*` output, so adjacent arguments could merge into values like `--restart=on-failure:10--label`. A space is now inserted at both the trigger echo and the concatenation so arguments always stay separated.
133 lines
5.5 KiB
Bash
Executable File
133 lines
5.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
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/scheduler-docker-local/internal-functions"
|
|
|
|
main() {
|
|
declare APP="$1" IMAGE_SOURCE_TYPE="$2" IMAGE="$3" IMAGE_TAG="$4" PROC_TYPE="$5" PROC_COUNT="$6" CONTAINER_INDEX="$7"
|
|
|
|
local cid=""
|
|
local port=""
|
|
local ipaddr=""
|
|
local DOKKU_CONTAINER_ID_FILE="$DOKKU_ROOT/$APP/CONTAINER.$PROC_TYPE.$CONTAINER_INDEX"
|
|
local DYNO="$PROC_TYPE.$CONTAINER_INDEX"
|
|
|
|
# start the app
|
|
local DOCKER_ARGS
|
|
DOCKER_ARGS=$(: | plugn trigger docker-args-deploy "$APP" "$IMAGE_TAG" "$PROC_TYPE" "$CONTAINER_INDEX")
|
|
DOCKER_ARGS+=" --label=com.dokku.process-type=$PROC_TYPE --label=com.dokku.dyno=$DYNO"
|
|
DOCKER_ARGS+=" --env=DYNO=$DYNO"
|
|
DOCKER_ARGS+=" --name=$APP.$DYNO.upcoming-$RANDOM"
|
|
if [[ "$INJECT_INIT_FLAG" == "true" ]]; then
|
|
DOCKER_ARGS+=" --init"
|
|
fi
|
|
DOCKER_ARGS+=" $DOCKER_RUN_LABEL_ARGS $DOKKU_GLOBAL_RUN_ARGS "
|
|
DOCKER_ARGS+=" $(: | plugn trigger docker-args-process-deploy "$APP" "$IMAGE_SOURCE_TYPE" "$IMAGE_TAG" "$PROC_TYPE" "$CONTAINER_INDEX")"
|
|
[[ "$DOKKU_TRACE" ]] && DOCKER_ARGS+=" --env=TRACE=true"
|
|
|
|
local START_CMD
|
|
[[ "$DOKKU_HEROKUISH" == "true" ]] && START_CMD="/start $PROC_TYPE"
|
|
[[ "$DOKKU_CNB" == "true" ]] && START_CMD=""
|
|
[[ -n "$DOKKU_START_CMD" ]] && START_CMD="$DOKKU_START_CMD"
|
|
|
|
local DOKKU_PORT=""
|
|
if [[ "$PROC_TYPE" == "web" ]]; then
|
|
ports=($(plugn trigger ports-get "$APP"))
|
|
local exposed_ports=()
|
|
for port_map in "${ports[@]}"; do
|
|
local scheme="$(echo "$port_map" | cut -d':' -f1)"
|
|
local container_port="$(echo "$port_map" | cut -d':' -f3)"
|
|
if [[ "$scheme" != "udp" ]]; then
|
|
DOKKU_PORT="${DOKKU_PORT:="$container_port"}"
|
|
fi
|
|
|
|
# skip if the exposed_ports array contains container_port
|
|
if fn-in-array "$container_port" "${exposed_ports[@]}"; then
|
|
continue
|
|
fi
|
|
|
|
if [[ "$DOKKU_NETWORK_BIND_ALL" == "true" ]]; then
|
|
exposed_ports+=("$container_port")
|
|
DOCKER_ARGS+=" -p $container_port"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
DOCKER_ARGS+=" --env=PORT=$DOKKU_PORT"
|
|
|
|
local DOKKU_IMAGE_ARCHITECTURE="$("$DOCKER_BIN" image inspect --format '{{.Architecture}}' "$IMAGE")"
|
|
if [[ "$DOKKU_IMAGE_ARCHITECTURE" == "amd64" ]] && [[ "$(dpkg --print-architecture 2>/dev/null || true)" != "amd64" ]]; then
|
|
dokku_log_warn "Detected linux/amd64 image, forcing --platform=linux/amd64"
|
|
DOCKER_ARGS+=" --platform=linux/amd64"
|
|
fi
|
|
|
|
START_CMD=$(fn-scheduler-docker-local-extract-start-cmd "$APP" "$PROC_TYPE" "$START_CMD" "$DOKKU_HEROKUISH" "$DOKKU_PORT")
|
|
DOCKER_ARGS+=" $IMAGE"
|
|
DOCKER_ARGS+=" $START_CMD"
|
|
|
|
declare -a ARG_ARRAY
|
|
eval "ARG_ARRAY=($DOCKER_ARGS)"
|
|
cid=$(fn-scheduler-docker-local-start-app-container "$APP" "${ARG_ARRAY[@]}")
|
|
|
|
plugn trigger post-container-create "app" "$cid" "$APP" "deploy" "$PROC_TYPE"
|
|
"$DOCKER_BIN" container start "$cid" >/dev/null || true
|
|
|
|
ipaddr=$(plugn trigger network-get-ipaddr "$APP" "$PROC_TYPE" "$cid")
|
|
|
|
kill_new() {
|
|
declare desc="wrapper function to kill newly started app container"
|
|
declare CID="$1" PROC_TYPE="$2" CONTAINER_INDEX="$3"
|
|
|
|
plugn trigger scheduler-register-retired "$APP" "$CID" "$DOKKU_WAIT_TO_RETIRE"
|
|
mkdir -p "${DOKKU_LIB_ROOT}/data/scheduler-docker-local/$APP"
|
|
echo "${CID} ${PROC_TYPE}.${CONTAINER_INDEX}" >>"${DOKKU_LIB_ROOT}/data/scheduler-docker-local/$APP/failed-containers"
|
|
"$DOCKER_BIN" container inspect "$CID" &>/dev/null && {
|
|
# Disable the container restart policy
|
|
"$DOCKER_BIN" container update --restart=no "$CID" &>/dev/null || true
|
|
"$DOCKER_BIN" container stop "$CID" >/dev/null && "$DOCKER_BIN" container kill "$CID" &>/dev/null
|
|
}
|
|
trap - INT TERM EXIT
|
|
kill -9 $$
|
|
}
|
|
|
|
# run checks first, then post-deploy hooks, which switches proxy traffic
|
|
trap "kill_new $cid $PROC_TYPE $CONTAINER_INDEX" INT TERM EXIT
|
|
if [[ "$DOKKU_CHECKS_DISABLED" == "false" ]]; then
|
|
dokku_log_verbose "Attempting pre-flight checks ($PROC_TYPE.$CONTAINER_INDEX)"
|
|
plugn trigger check-deploy "$APP" "$cid" "$PROC_TYPE" "$DOKKU_PORT" "$ipaddr" "$CONTAINER_INDEX"
|
|
fi
|
|
trap - INT TERM EXIT
|
|
|
|
if [[ -f "$DOKKU_CONTAINER_ID_FILE" ]]; then
|
|
# schedule old container for retirement
|
|
dokku_log_verbose "Scheduling old container shutdown in $DOKKU_WAIT_TO_RETIRE seconds ($PROC_TYPE.$CONTAINER_INDEX)"
|
|
plugn trigger scheduler-register-retired "$APP" "$(cat "$DOKKU_CONTAINER_ID_FILE")" "$DOKKU_WAIT_TO_RETIRE"
|
|
fi
|
|
|
|
# now using the new container
|
|
[[ -n "$cid" ]] && echo "$cid" >"$DOKKU_CONTAINER_ID_FILE"
|
|
[[ -n "$ipaddr" ]] && plugn trigger network-write-ipaddr "$APP" "$PROC_TYPE" "$CONTAINER_INDEX" "$ipaddr"
|
|
[[ -n "$DOKKU_PORT" ]] && plugn trigger network-write-port "$APP" "$PROC_TYPE" "$CONTAINER_INDEX" "$DOKKU_PORT"
|
|
|
|
# cleanup pre-migration files
|
|
rm -f "$DOKKU_ROOT/$APP/CONTAINER" "$DOKKU_ROOT/$APP/IP" "$DOKKU_ROOT/$APP/PORT"
|
|
}
|
|
|
|
fn-scheduler-docker-local-extract-start-cmd() {
|
|
declare APP="$1" PROC_TYPE="$2" START_CMD="$3" DOKKU_HEROKUISH="$4" PORT="$5"
|
|
local DOKKU_DOCKERFILE_START_CMD DOKKU_PROCFILE_START_CMD START_CMD
|
|
if [[ "$DOKKU_HEROKUISH" != "false" ]] && [[ -n "$START_CMD" ]]; then
|
|
echo "$START_CMD"
|
|
return
|
|
fi
|
|
|
|
DOKKU_DOCKERFILE_START_CMD=$(fn-plugin-property-get-default "ps" "$APP" "dockerfile-start-cmd" "")
|
|
DOKKU_PROCFILE_START_CMD=$(plugn trigger procfile-get-command "$APP" "$PROC_TYPE" "$PORT" 2>/dev/null || echo '')
|
|
START_CMD=${DOKKU_DOCKERFILE_START_CMD:-$DOKKU_PROCFILE_START_CMD}
|
|
echo "$START_CMD"
|
|
}
|
|
|
|
main "$@"
|