166 lines
6.7 KiB
Bash
Executable File
166 lines
6.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
|
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
|
source "$PLUGIN_AVAILABLE_PATH/checks/functions"
|
|
source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
|
source "$PLUGIN_CORE_AVAILABLE_PATH/proxy/functions"
|
|
|
|
dokku_deploy_cmd() {
|
|
declare desc="deploy phase"
|
|
local cmd="deploy"
|
|
[[ -z $2 ]] && dokku_log_fail "Please specify an app to deploy"
|
|
local APP="$2"; local IMAGE_TAG="$3"; local IMAGE=$(get_app_image_name "$APP" "$IMAGE_TAG")
|
|
verify_app_name "$APP"
|
|
plugn trigger pre-deploy "$APP" "$IMAGE_TAG"
|
|
|
|
is_image_herokuish_based "$IMAGE" && local DOKKU_HEROKUISH=true
|
|
local DOKKU_SCALE_FILE="$DOKKU_ROOT/$APP/DOKKU_SCALE"
|
|
local oldids=$(get_app_container_ids "$APP")
|
|
|
|
local DOKKU_DEFAULT_DOCKER_ARGS=$(: | plugn trigger docker-args-deploy "$APP" "$IMAGE_TAG")
|
|
local DOKKU_IS_APP_PROXY_ENABLED="$(is_app_proxy_enabled "$APP")"
|
|
|
|
local line; local PROC_TYPE; local PROC_COUNT; local CONTAINER_INDEX
|
|
while read -r line || [[ -n "$line" ]]; do
|
|
[[ "$line" =~ ^#.* ]] && continue
|
|
line="$(strip_inline_comments "$line")"
|
|
PROC_TYPE=${line%%=*}
|
|
PROC_COUNT=${line#*=}
|
|
CONTAINER_INDEX=1
|
|
|
|
while [[ $CONTAINER_INDEX -le $PROC_COUNT ]]; do
|
|
local id=""; local port=""; local ipaddr=""
|
|
local DOKKU_CONTAINER_ID_FILE="$DOKKU_ROOT/$APP/CONTAINER.$PROC_TYPE.$CONTAINER_INDEX"
|
|
local DOKKU_IP_FILE="$DOKKU_ROOT/$APP/IP.$PROC_TYPE.$CONTAINER_INDEX"
|
|
local DOKKU_PORT_FILE="$DOKKU_ROOT/$APP/PORT.$PROC_TYPE.$CONTAINER_INDEX"
|
|
|
|
# start the app
|
|
local DOCKER_ARGS="$DOKKU_DEFAULT_DOCKER_ARGS"
|
|
local DOCKER_ARGS+=" -e DYNO='$PROC_TYPE.$CONTAINER_INDEX' "
|
|
[[ "$DOKKU_TRACE" ]] && local DOCKER_ARGS+=" -e TRACE=true "
|
|
|
|
[[ -n "$DOKKU_HEROKUISH" ]] && local START_CMD="/start $PROC_TYPE"
|
|
|
|
if [[ -z "$DOKKU_HEROKUISH" ]]; then
|
|
local DOKKU_DOCKERFILE_PORTS=($(config_get "$APP" DOKKU_DOCKERFILE_PORTS || true))
|
|
local DOKKU_DOCKERFILE_START_CMD=$(config_get "$APP" DOKKU_DOCKERFILE_START_CMD || true)
|
|
local DOKKU_PROCFILE_START_CMD=$(get_cmd_from_procfile "$APP" "$PROC_TYPE")
|
|
local START_CMD=${DOKKU_DOCKERFILE_START_CMD:-$DOKKU_PROCFILE_START_CMD}
|
|
fi
|
|
|
|
if [[ "$PROC_TYPE" == "web" ]]; then
|
|
if [[ -z "${DOKKU_DOCKERFILE_PORTS[*]}" ]]; then
|
|
local port=5000
|
|
local DOKKU_DOCKER_PORT_ARGS+="-p $port"
|
|
else
|
|
local p
|
|
for p in ${DOKKU_DOCKERFILE_PORTS[*]};do
|
|
if [[ ! "$p" =~ .*udp.* ]]; then
|
|
# set port to first non-udp port
|
|
local p=${p//\/tcp}
|
|
local port=${port:="$p"}
|
|
fi
|
|
local DOKKU_DOCKER_PORT_ARGS+=" -p $p "
|
|
done
|
|
fi
|
|
if [[ "$DOKKU_IS_APP_PROXY_ENABLED" == "true" ]]; then
|
|
# shellcheck disable=SC2086
|
|
local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d -e PORT=$port $DOCKER_ARGS $IMAGE $START_CMD)
|
|
local ipaddr=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$id")
|
|
# Docker < 1.9 compatibility
|
|
if [[ -z $ipaddr ]]; then
|
|
local ipaddr=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$id")
|
|
fi
|
|
else
|
|
# shellcheck disable=SC2086
|
|
local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d $DOKKU_DOCKER_PORT_ARGS -e PORT=$port $DOCKER_ARGS $IMAGE $START_CMD)
|
|
local port=$(docker port "$id" "$port" | sed 's/[0-9.]*://')
|
|
local ipaddr=127.0.0.1
|
|
fi
|
|
else
|
|
# shellcheck disable=SC2086
|
|
local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d $DOCKER_ARGS $IMAGE $START_CMD)
|
|
fi
|
|
|
|
# if we can't post-deploy successfully, kill new container
|
|
kill_new() {
|
|
declare desc="wrapper function to kill newly started app container"
|
|
local id="$1"
|
|
docker inspect "$id" &> /dev/null && docker stop "$id" > /dev/null && docker kill "$id" &> /dev/null
|
|
trap - INT TERM EXIT
|
|
kill -9 $$
|
|
}
|
|
|
|
# run checks first, then post-deploy hooks, which switches Nginx traffic
|
|
if [[ "$(is_app_checks_enabled "$APP")" == "false" ]]; then
|
|
dokku_log_info1 "zero downtime is disabled for app ($APP). skipping pre-flight checks"
|
|
else
|
|
trap 'kill_new $id' INT TERM EXIT
|
|
dokku_log_info1 "Running pre-flight checks"
|
|
plugn trigger check-deploy "$APP" "$id" "$PROC_TYPE" "$port" "$ipaddr"
|
|
trap - INT TERM EXIT
|
|
fi
|
|
|
|
# now using the new container
|
|
[[ -n "$id" ]] && echo "$id" > "$DOKKU_CONTAINER_ID_FILE"
|
|
[[ -n "$ipaddr" ]] && echo "$ipaddr" > "$DOKKU_IP_FILE"
|
|
[[ -n "$port" ]] && echo "$port" > "$DOKKU_PORT_FILE"
|
|
|
|
# cleanup pre-migration files
|
|
rm -f "$DOKKU_ROOT/$APP/CONTAINER" "$DOKKU_ROOT/$APP/IP" "$DOKKU_ROOT/$APP/PORT"
|
|
|
|
local CONTAINER_INDEX=$(( CONTAINER_INDEX + 1 ))
|
|
done
|
|
# cleanup when we scale down
|
|
if [[ "$PROC_COUNT" == 0 ]]; then
|
|
local CONTAINER_IDX_OFFSET=0
|
|
else
|
|
local CONTAINER_IDX_OFFSET=$((PROC_COUNT + 1))
|
|
fi
|
|
local container_state_filetype
|
|
for container_state_filetype in CONTAINER IP PORT; do
|
|
cd "$DOKKU_ROOT/$APP"
|
|
find . -maxdepth 1 -name "$container_state_filetype.$PROC_TYPE.*" -printf "%f\n" | sort -t . -k 3 -n | tail -n +$CONTAINER_IDX_OFFSET | xargs rm -f
|
|
done
|
|
done < "$DOKKU_SCALE_FILE"
|
|
|
|
dokku_log_info1 "Running post-deploy"
|
|
plugn trigger post-deploy "$APP" "$port" "$ipaddr" "$IMAGE_TAG"
|
|
|
|
# kill the old container
|
|
if [[ -n "$oldids" ]]; then
|
|
|
|
if [[ -z "$DOKKU_WAIT_TO_RETIRE" ]]; then
|
|
local DOKKU_APP_DOKKU_WAIT_TO_RETIRE=$(config_get "$APP" DOKKU_WAIT_TO_RETIRE || true)
|
|
local DOKKU_GLOBAL_DOKKU_WAIT_TO_RETIRE=$(config_get --global DOKKU_WAIT_TO_RETIRE || true)
|
|
local DOKKU_WAIT_TO_RETIRE=${DOKKU_APP_DOKKU_WAIT_TO_RETIRE:="$DOKKU_GLOBAL_DOKKU_WAIT_TO_RETIRE"}
|
|
fi
|
|
|
|
# Let the old container finish processing requests, before terminating it
|
|
local WAIT="${DOKKU_WAIT_TO_RETIRE:-60}"
|
|
dokku_log_info1 "Shutting down old containers in $WAIT seconds"
|
|
local oldid
|
|
for oldid in $oldids; do
|
|
dokku_log_info2 "$oldid"
|
|
done
|
|
(
|
|
exec >/dev/null 2>/dev/null </dev/null
|
|
trap '' INT HUP
|
|
sleep "$WAIT"
|
|
for oldid in $oldids; do
|
|
# Attempt to stop, if that fails, then force a kill as docker seems
|
|
# to not send SIGKILL as the docs would indicate. If that fails, move
|
|
# on to the next.
|
|
docker stop "$oldid" \
|
|
|| docker kill "$oldid" \
|
|
|| plugn trigger retire-container-failed "$APP" # plugin trigger for event logging
|
|
done
|
|
) & disown -a
|
|
# Use trap since disown/nohup don't seem to keep child alive
|
|
# Give child process just enough time to set the traps
|
|
sleep 0.1
|
|
fi
|
|
}
|
|
|
|
dokku_deploy_cmd "$@"
|