From ce3aa4b93edcf4ba786a17515ddfd2db32e1a175 Mon Sep 17 00:00:00 2001 From: Michael Hobbs Date: Fri, 17 Jun 2016 16:40:35 -0700 Subject: [PATCH] remove calls to dokku binary for build/receive/release --- docs/development/plugin-triggers.md | 18 +- dokku | 7 +- plugins/00_dokku-standard/subcommands/build | 65 ---- plugins/00_dokku-standard/subcommands/deploy | 171 +---------- plugins/00_dokku-standard/subcommands/receive | 22 -- plugins/00_dokku-standard/subcommands/release | 40 --- plugins/common/functions | 287 +++++++++++++++++- plugins/config/functions | 8 +- plugins/git/functions | 4 +- plugins/tar/functions | 4 +- 10 files changed, 307 insertions(+), 319 deletions(-) delete mode 100755 plugins/00_dokku-standard/subcommands/build delete mode 100755 plugins/00_dokku-standard/subcommands/receive delete mode 100755 plugins/00_dokku-standard/subcommands/release diff --git a/docs/development/plugin-triggers.md b/docs/development/plugin-triggers.md index 4b2933f44..44bb1cbcb 100644 --- a/docs/development/plugin-triggers.md +++ b/docs/development/plugin-triggers.md @@ -164,7 +164,7 @@ esac ### `docker-args-build` - Description: -- Invoked by: `dokku build` +- Invoked by: `dokku_build` - Arguments: `$APP $IMAGE_SOURCE_TYPE` - Example: @@ -300,7 +300,7 @@ nginx -t ### `post-build-buildpack` - Description: Allows you to run commands after the build image is create for a given app. Only applies to applications using buildpacks. -- Invoked by: `dokku build` +- Invoked by: `dokku_build` - Arguments: `$APP` - Example: @@ -315,7 +315,7 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x ### `post-build-dockerfile` - Description: Allows you to run commands after the build image is create for a given app. Only applies to applications using a dockerfile. -- Invoked by: `dokku build` +- Invoked by: `dokku_build` - Arguments: `$APP` - Example: @@ -423,7 +423,7 @@ haproxy-build-config "$APP" ### `post-release-buildpack` - Description: Allows you to run commands after environment variables are set for the release step of the deploy. Only applies to applications using buildpacks. -- Invoked by: `dokku release` +- Invoked by: `dokku_release` - Arguments: `$APP $IMAGE_TAG` - Example: @@ -450,7 +450,7 @@ docker commit $ID $IMAGE > /dev/null ### `post-release-dockerfile` - Description: Allows you to run commands after environment variables are set for the release step of the deploy. Only applies to applications using a dockerfile. -- Invoked by: `dokku release` +- Invoked by: `dokku_release` - Arguments: `$APP $IMAGE_TAG` - Example: @@ -486,7 +486,7 @@ dokku config:set --no-restart $APP MANUALLY_STOPPED=1 ### `pre-build-buildpack` - Description: Allows you to run commands before the build image is created for a given app. For instance, this can be useful to add env vars to your container. Only applies to applications using buildpacks. -- Invoked by: `dokku build` +- Invoked by: `dokku_build` - Arguments: `$APP` - Example: @@ -501,7 +501,7 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x ### `pre-build-dockerfile` - Description: Allows you to run commands before the build image is created for a given app. For instance, this can be useful to add env vars to your container. Only applies to applications using a dockerfile. -- Invoked by: `dokku build` +- Invoked by: `dokku_build` - Arguments: `$APP` - Example: @@ -580,7 +580,7 @@ echo "$APP" > "$TMP_WORK_DIR/dokku-is-awesome" ### `pre-release-buildpack` - Description: Allows you to run commands before environment variables are set for the release step of the deploy. Only applies to applications using buildpacks. -- Invoked by: `dokku release` +- Invoked by: `dokku_release` - Arguments: `$APP $IMAGE_TAG` - Example: @@ -607,7 +607,7 @@ docker commit $ID $IMAGE > /dev/null ### `pre-release-dockerfile` - Description: Allows you to run commands before environment variables are set for the release step of the deploy. Only applies to applications using a dockerfile. -- Invoked by: `dokku release` +- Invoked by: `dokku_release` - Arguments: `$APP $IMAGE_TAG` - Example: diff --git a/dokku b/dokku index b80742acc..4238b4f10 100755 --- a/dokku +++ b/dokku @@ -100,13 +100,10 @@ execute_dokku_cmd() { nginx|nginx:*) local PLUGIN_NAME=${PLUGIN_NAME/nginx/nginx-vhosts} ;; - receive|deploy|build|release) + deploy|delete|ls|run|cleanup) local PLUGIN_NAME="00_dokku-standard" ;; - trace|delete|ls|run|cleanup) - local PLUGIN_NAME="00_dokku-standard" - ;; - url|urls|report|version) + trace|url|urls|report|version) local PLUGIN_NAME="00_dokku-standard" ;; esac diff --git a/plugins/00_dokku-standard/subcommands/build b/plugins/00_dokku-standard/subcommands/build deleted file mode 100755 index 4df74e26b..000000000 --- a/plugins/00_dokku-standard/subcommands/build +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" -source "$PLUGIN_AVAILABLE_PATH/config/functions" - -dokku_build_cmd() { - declare desc="build phase" - local cmd="build" - local APP="$2"; local IMAGE_SOURCE_TYPE="$3"; local TMP_WORK_DIR="$4"; local IMAGE=$(get_app_image_name "$APP") - verify_app_name "$APP" - - local CACHE_DIR="$DOKKU_ROOT/$APP/cache" - - eval "$(config_export app "$APP")" - pushd "$TMP_WORK_DIR" &> /dev/null - - case "$IMAGE_SOURCE_TYPE" in - herokuish) - local id=$(tar -c . | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$DOKKU_IMAGE" /bin/bash -c "mkdir -p /app && tar -xC /app") - test "$(docker wait "$id")" -eq 0 - docker commit "$id" "$IMAGE" > /dev/null - [[ -d $CACHE_DIR ]] || mkdir -p "$CACHE_DIR" - plugn trigger pre-build-buildpack "$APP" - - local DOCKER_ARGS=$(: | plugn trigger docker-args-build "$APP" "$IMAGE_SOURCE_TYPE") - [[ "$DOKKU_TRACE" ]] && DOCKER_ARGS+=" -e TRACE=true " - # shellcheck disable=SC2086 - local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d -v $CACHE_DIR:/cache -e CACHE_PATH=/cache $DOCKER_ARGS $IMAGE /build) - docker attach "$id" - test "$(docker wait "$id")" -eq 0 - docker commit "$id" "$IMAGE" > /dev/null - - plugn trigger post-build-buildpack "$APP" - ;; - - dockerfile) - # extract first port from Dockerfile - local DOCKERFILE_PORTS=$(get_dockerfile_exposed_ports Dockerfile) - [[ -n "$DOCKERFILE_PORTS" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_PORTS="$DOCKERFILE_PORTS" - - # extract ENTRYPOINT/CMD from Dockerfile - local DOCKERFILE_ENTRYPOINT=$(extract_directive_from_dockerfile Dockerfile ENTRYPOINT) - [[ -n "$DOCKERFILE_ENTRYPOINT" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_ENTRYPOINT="$DOCKERFILE_ENTRYPOINT" - local DOCKERFILE_CMD=$(extract_directive_from_dockerfile Dockerfile CMD) - [[ -n "$DOCKERFILE_CMD" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_CMD="$DOCKERFILE_CMD" - plugn trigger pre-build-dockerfile "$APP" - - [[ "$DOKKU_DOCKERFILE_CACHE_BUILD" == "false" ]] && DOKKU_DOCKER_BUILD_OPTS="$DOKKU_DOCKER_BUILD_OPTS --no-cache" - local DOCKER_ARGS=$(: | plugn trigger docker-args-build "$APP" "$IMAGE_SOURCE_TYPE") - # strip --volume and -v args from DOCKER_ARGS - local DOCKER_ARGS=$(sed -e "s/--volume=[[:graph:]]\+[[:blank:]]\?//g" -e "s/-v[[:blank:]]\?[[:graph:]]\+[[:blank:]]\?//g" <<< "$DOCKER_ARGS") - - # shellcheck disable=SC2086 - docker build $DOCKER_ARGS $DOKKU_DOCKER_BUILD_OPTS -t $IMAGE . - - plugn trigger post-build-dockerfile "$APP" - ;; - - *) - dokku_log_fail "Building image source type $IMAGE_SOURCE_TYPE not supported!" - ;; - esac -} - -dokku_build_cmd "$@" diff --git a/plugins/00_dokku-standard/subcommands/deploy b/plugins/00_dokku-standard/subcommands/deploy index 68f1a2252..888165a4c 100755 --- a/plugins/00_dokku-standard/subcommands/deploy +++ b/plugins/00_dokku-standard/subcommands/deploy @@ -1,175 +1,6 @@ #!/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_deploying_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 DOKKU_DOCKER_STOP_TIMEOUT="$(config_get "$APP" DOKKU_DOCKER_STOP_TIMEOUT || true)" - [[ $DOKKU_DOCKER_STOP_TIMEOUT ]] && DOCKER_STOP_TIME_ARG="--time=${DOKKU_DOCKER_STOP_TIMEOUT}" - - 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 - - if [[ "$(is_app_proctype_checks_disabled "$APP" "$PROC_TYPE")" == "true" ]]; then - dokku_log_info1 "zero downtime is disabled for app ($APP.$PROC_TYPE). stopping currently running containers" - local cid proctype_oldids="$(get_app_container_ids "$APP" "$PROC_TYPE")" - for cid in $proctype_oldids; do - dokku_log_info2 "stopping $APP.$PROC_TYPE ($cid)" - # shellcheck disable=SC2086 - docker stop $DOCKER_STOP_TIME_ARG "$cid" &> /dev/null - done - fi - - 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 - - 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 proxy traffic - trap 'kill_new $id' INT TERM EXIT - if [[ "$(is_app_proctype_checks_disabled "$APP" "$PROC_TYPE")" == "false" ]]; then - dokku_log_info1 "Attempting pre-flight checks" - plugn trigger check-deploy "$APP" "$id" "$PROC_TYPE" "$port" "$ipaddr" - fi - trap - INT TERM EXIT - - # 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 - dokku build "$APP" "$IMAGE_SOURCE_TYPE" "$TMP_WORK_DIR" - release_and_deploy "$APP" -} - -dokku_receive_cmd "$@" diff --git a/plugins/00_dokku-standard/subcommands/release b/plugins/00_dokku-standard/subcommands/release deleted file mode 100755 index 7dc148014..000000000 --- a/plugins/00_dokku-standard/subcommands/release +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" -source "$PLUGIN_AVAILABLE_PATH/config/functions" - -dokku_release_cmd() { - declare desc="release phase" - local cmd="release" - local APP="$2"; local IMAGE_SOURCE_TYPE="$3"; local IMAGE_TAG="$4"; local IMAGE=$(get_app_image_name "$APP" "$IMAGE_TAG") - verify_app_name "$APP" - - case "$IMAGE_SOURCE_TYPE" in - herokuish) - plugn trigger pre-release-buildpack "$APP" "$IMAGE_TAG" - if [[ -n $(config_export global) ]]; then - local id=$(config_export global | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$IMAGE" /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/00-global-env.sh") - test "$(docker wait "$id")" -eq 0 - docker commit "$id" "$IMAGE" > /dev/null - fi - if [[ -n $(config_export app "$APP") ]]; then - local id=$(config_export app "$APP" | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$IMAGE" /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/01-app-env.sh") - test "$(docker wait "$id")" -eq 0 - docker commit "$id" "$IMAGE" > /dev/null - fi - plugn trigger post-release-buildpack "$APP" "$IMAGE_TAG" - ;; - - dockerfile) - # buildstep plugins don't necessarily make sense for dockerfiles. call the new breed!!! - plugn trigger pre-release-dockerfile "$APP" "$IMAGE_TAG" - plugn trigger post-release-dockerfile "$APP" "$IMAGE_TAG" - ;; - - *) - dokku_log_fail "Releasing image source type $IMAGE_SOURCE_TYPE not supported!" - ;; - esac -} - -dokku_release_cmd "$@" diff --git a/plugins/common/functions b/plugins/common/functions index 97279f404..c495e8af1 100755 --- a/plugins/common/functions +++ b/plugins/common/functions @@ -414,6 +414,272 @@ is_app_running() { fi } +dokku_build() { + declare desc="build phase" + source "$PLUGIN_AVAILABLE_PATH/config/functions" + + local APP="$1"; local IMAGE_SOURCE_TYPE="$2"; local TMP_WORK_DIR="$3"; local IMAGE=$(get_app_image_name "$APP") + verify_app_name "$APP" + + local CACHE_DIR="$DOKKU_ROOT/$APP/cache" + + eval "$(config_export app "$APP")" + pushd "$TMP_WORK_DIR" &> /dev/null + + case "$IMAGE_SOURCE_TYPE" in + herokuish) + local id=$(tar -c . | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$DOKKU_IMAGE" /bin/bash -c "mkdir -p /app && tar -xC /app") + test "$(docker wait "$id")" -eq 0 + docker commit "$id" "$IMAGE" > /dev/null + [[ -d $CACHE_DIR ]] || mkdir -p "$CACHE_DIR" + plugn trigger pre-build-buildpack "$APP" + + local DOCKER_ARGS=$(: | plugn trigger docker-args-build "$APP" "$IMAGE_SOURCE_TYPE") + [[ "$DOKKU_TRACE" ]] && DOCKER_ARGS+=" -e TRACE=true " + # shellcheck disable=SC2086 + local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d -v $CACHE_DIR:/cache -e CACHE_PATH=/cache $DOCKER_ARGS $IMAGE /build) + docker attach "$id" + test "$(docker wait "$id")" -eq 0 + docker commit "$id" "$IMAGE" > /dev/null + + plugn trigger post-build-buildpack "$APP" + ;; + + dockerfile) + # extract first port from Dockerfile + local DOCKERFILE_PORTS=$(get_dockerfile_exposed_ports Dockerfile) + [[ -n "$DOCKERFILE_PORTS" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_PORTS="$DOCKERFILE_PORTS" + + # extract ENTRYPOINT/CMD from Dockerfile + local DOCKERFILE_ENTRYPOINT=$(extract_directive_from_dockerfile Dockerfile ENTRYPOINT) + [[ -n "$DOCKERFILE_ENTRYPOINT" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_ENTRYPOINT="$DOCKERFILE_ENTRYPOINT" + local DOCKERFILE_CMD=$(extract_directive_from_dockerfile Dockerfile CMD) + [[ -n "$DOCKERFILE_CMD" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_CMD="$DOCKERFILE_CMD" + plugn trigger pre-build-dockerfile "$APP" + + [[ "$DOKKU_DOCKERFILE_CACHE_BUILD" == "false" ]] && DOKKU_DOCKER_BUILD_OPTS="$DOKKU_DOCKER_BUILD_OPTS --no-cache" + local DOCKER_ARGS=$(: | plugn trigger docker-args-build "$APP" "$IMAGE_SOURCE_TYPE") + # strip --volume and -v args from DOCKER_ARGS + local DOCKER_ARGS=$(sed -e "s/--volume=[[:graph:]]\+[[:blank:]]\?//g" -e "s/-v[[:blank:]]\?[[:graph:]]\+[[:blank:]]\?//g" <<< "$DOCKER_ARGS") + + # shellcheck disable=SC2086 + docker build $DOCKER_ARGS $DOKKU_DOCKER_BUILD_OPTS -t $IMAGE . + + plugn trigger post-build-dockerfile "$APP" + ;; + + *) + dokku_log_fail "Building image source type $IMAGE_SOURCE_TYPE not supported!" + ;; + esac +} + +dokku_release() { + declare desc="release phase" + source "$PLUGIN_AVAILABLE_PATH/config/functions" + + local APP="$1"; local IMAGE_SOURCE_TYPE="$2"; local IMAGE_TAG="$3"; local IMAGE=$(get_app_image_name "$APP" "$IMAGE_TAG") + verify_app_name "$APP" + + case "$IMAGE_SOURCE_TYPE" in + herokuish) + plugn trigger pre-release-buildpack "$APP" "$IMAGE_TAG" + if [[ -n $(config_export global) ]]; then + local id=$(config_export global | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$IMAGE" /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/00-global-env.sh") + test "$(docker wait "$id")" -eq 0 + docker commit "$id" "$IMAGE" > /dev/null + fi + if [[ -n $(config_export app "$APP") ]]; then + local id=$(config_export app "$APP" | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$IMAGE" /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/01-app-env.sh") + test "$(docker wait "$id")" -eq 0 + docker commit "$id" "$IMAGE" > /dev/null + fi + plugn trigger post-release-buildpack "$APP" "$IMAGE_TAG" + ;; + + dockerfile) + # buildstep plugins don't necessarily make sense for dockerfiles. call the new breed!!! + plugn trigger pre-release-dockerfile "$APP" "$IMAGE_TAG" + plugn trigger post-release-dockerfile "$APP" "$IMAGE_TAG" + ;; + + *) + dokku_log_fail "Releasing image source type $IMAGE_SOURCE_TYPE not supported!" + ;; + esac +} + +dokku_deploy_cmd() { + declare desc="deploy phase" + local cmd="deploy" + source "$PLUGIN_AVAILABLE_PATH/checks/functions" + source "$PLUGIN_AVAILABLE_PATH/config/functions" + source "$PLUGIN_CORE_AVAILABLE_PATH/proxy/functions" + + [[ -z $1 ]] && dokku_log_fail "Please specify an app to deploy" + local APP="$1"; local IMAGE_TAG="$2"; local IMAGE=$(get_deploying_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 DOKKU_DOCKER_STOP_TIMEOUT="$(config_get "$APP" DOKKU_DOCKER_STOP_TIMEOUT || true)" + [[ $DOKKU_DOCKER_STOP_TIMEOUT ]] && DOCKER_STOP_TIME_ARG="--time=${DOKKU_DOCKER_STOP_TIMEOUT}" + + 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 + + if [[ "$(is_app_proctype_checks_disabled "$APP" "$PROC_TYPE")" == "true" ]]; then + dokku_log_info1 "zero downtime is disabled for app ($APP.$PROC_TYPE). stopping currently running containers" + local cid proctype_oldids="$(get_app_container_ids "$APP" "$PROC_TYPE")" + for cid in $proctype_oldids; do + dokku_log_info2 "stopping $APP.$PROC_TYPE ($cid)" + # shellcheck disable=SC2086 + docker stop $DOCKER_STOP_TIME_ARG "$cid" &> /dev/null + done + fi + + 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 + + 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 proxy traffic + trap 'kill_new $id' INT TERM EXIT + if [[ "$(is_app_proctype_checks_disabled "$APP" "$PROC_TYPE")" == "false" ]]; then + dokku_log_info1 "Attempting pre-flight checks" + plugn trigger check-deploy "$APP" "$id" "$PROC_TYPE" "$port" "$ipaddr" + fi + trap - INT TERM EXIT + + # 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 + dokku_build "$APP" "$IMAGE_SOURCE_TYPE" "$TMP_WORK_DIR" + release_and_deploy "$APP" +} + docker_cleanup() { declare desc="cleans up all exited/dead containers and removes all dangling images" # delete all non-running containers diff --git a/plugins/config/functions b/plugins/config/functions index b2a1e8365..c97ff7c57 100755 --- a/plugins/config/functions +++ b/plugins/config/functions @@ -160,6 +160,8 @@ config_get() { config_set() { declare desc="set value of given config var" + source "$PLUGIN_AVAILABLE_PATH/ps/functions" + [[ "$1" == "config:set" ]] || set -- "config:set" "$@" config_parse_args "$@" @@ -214,12 +216,14 @@ ${var}" [[ $APP ]] && local DOKKU_APP_RESTORE=$(config_get "$APP" DOKKU_APP_RESTORE || true) if [[ "$DOKKU_CONFIG_RESTART" == "true" ]] && [[ "$DOKKU_APP_RESTORE" != 0 ]]; then dokku_log_info1 "Restarting app $APP" - dokku ps:restart "$APP" + ps_restart "$APP" fi } config_unset() { declare desc="unset given config var" + source "$PLUGIN_AVAILABLE_PATH/ps/functions" + [[ "$1" == "config:unset" ]] || set -- "config:unset" "$@" config_parse_args "$@" local SANITIZED_ARGS=($(get_sanitized_config_args "$@")) @@ -247,6 +251,6 @@ config_unset() { [[ $APP ]] && local DOKKU_APP_RESTORE=$(config_get "$APP" DOKKU_APP_RESTORE || true) if [[ "$DOKKU_CONFIG_RESTART" == "true" ]] && [[ "$DOKKU_APP_RESTORE" != 0 ]]; then dokku_log_info1 "Restarting app $APP" - dokku ps:restart "$APP" + ps_restart "$APP" fi } diff --git a/plugins/git/functions b/plugins/git/functions index a20f8414e..33158d646 100755 --- a/plugins/git/functions +++ b/plugins/git/functions @@ -34,10 +34,10 @@ git_build_app_repo() { if [[ -f Dockerfile ]] && [[ "$([[ -f .env ]] && grep -q BUILDPACK_URL .env; echo $?)" != "0" ]] && [[ ! -f ".buildpacks" ]] && [[ -z $(config_get "$APP" BUILDPACK_URL || true) ]]; then plugn trigger pre-receive-app "$APP" "dockerfile" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" "$REV" - dokku receive "$APP" "dockerfile" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" + dokku_receive "$APP" "dockerfile" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" else plugn trigger pre-receive-app "$APP" "herokuish" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" "$REV" - dokku receive "$APP" "herokuish" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" + dokku_receive "$APP" "herokuish" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" fi } diff --git a/plugins/tar/functions b/plugins/tar/functions index 4581677aa..93b024645 100755 --- a/plugins/tar/functions +++ b/plugins/tar/functions @@ -26,10 +26,10 @@ tar_build() { if [[ -f Dockerfile ]] && [[ "$([[ -f .env ]] && grep -q BUILDPACK_URL .env; echo $?)" != "0" ]] && [[ ! -f ".buildpacks" ]]; then plugn trigger pre-receive-app "$APP" "dockerfile" "$TAR_BUILD_TMP_WORK_DIR" - dokku receive "$APP" "dockerfile" "$TAR_BUILD_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" + dokku_receive "$APP" "dockerfile" "$TAR_BUILD_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" else plugn trigger pre-receive-app "$APP" "herokuish" "$TAR_BUILD_TMP_WORK_DIR" - dokku receive "$APP" "herokuish" "$TAR_BUILD_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" + dokku_receive "$APP" "herokuish" "$TAR_BUILD_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" fi }