diff --git a/docs/process-management.md b/docs/process-management.md new file mode 100644 index 000000000..619ec8f60 --- /dev/null +++ b/docs/process-management.md @@ -0,0 +1,13 @@ +# Process/Container management + +Dokku supports rudimentary process (really container) management via the `ps` plugin. + +``` +ps List processes running in app container(s) +ps:start Start app container(s) +ps:stop Stop app container(s) +ps:restart Restart app container(s) +ps:restartall Restart all deployed app containers +``` + +*NOTE*: As of v0.3.14, `dokku deploy:all` in now deprecated by `ps:restartall` and will be removed in a future version. diff --git a/docs/upgrading.md b/docs/upgrading.md index bf7776c8c..1f49f6adc 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -60,7 +60,7 @@ There is an upgrade [script](https://gist.github.com/plietar/7201430), which is 1. run the script as root 2. `git pull` to get the latest version of dokku 3. make install -4. `dokku deploy:all` +4. `dokku ps:restartall` TDB. diff --git a/dokku b/dokku index 117cecf16..a73c96296 100755 --- a/dokku +++ b/dokku @@ -160,12 +160,10 @@ case "$1" in pluginhook update ;; - # temporary hack for https://github.com/progrium/dokku/issues/82 + # DEPRECATED as of v0.3.14 deploy:all) - for app in $DOKKU_ROOT/*/CONTAINER; do - APP=$(basename "$(dirname $app)"); - dokku deploy $APP - done + echo "*DEPRECATED* in v0.3.14: deploy:all will be removed in future versions" + dokku ps:restartall ;; help|'') diff --git a/plugins/00_dokku-standard/install b/plugins/00_dokku-standard/install index 91e93d2d8..02d743a18 100755 --- a/plugins/00_dokku-standard/install +++ b/plugins/00_dokku-standard/install @@ -20,7 +20,7 @@ start on (started docker) script sleep 2 # give docker some time - sudo -i -u dokku /usr/local/bin/dokku deploy:all + sudo -i -u dokku /usr/local/bin/dokku ps:restartall end script EOF ;; @@ -34,7 +34,7 @@ After=docker.target [Service] Type=simple User=dokku -ExecStart=/usr/local/bin/dokku deploy:all +ExecStart=/usr/local/bin/dokku ps:restartall [Install] WantedBy=multi-user.target diff --git a/plugins/config/commands b/plugins/config/commands index bb46313e2..f6d73e017 100755 --- a/plugins/config/commands +++ b/plugins/config/commands @@ -35,26 +35,13 @@ config_styled_hash () { done <<< "$vars" } -config_restart_app() { - APP="$1"; - - if [[ -f "$DOKKU_ROOT/$APP/CONTAINER" ]]; then - echo "-----> Releasing $APP ..." - dokku release $APP - echo "-----> Release complete!" - echo "-----> Deploying $APP ..." - dokku deploy $APP - echo "-----> Deploy complete!" - fi -} - config_write() { ENV_TEMP="$1" echo -e "$ENV_TEMP" | sed '/^$/d' | sort > $ENV_FILE_TEMP if ! cmp -s $ENV_FILE $ENV_FILE_TEMP; then cp -f $ENV_FILE_TEMP $ENV_FILE chmod 600 $ENV_FILE - config_restart_app $APP + dokku ps:restart $APP fi rm -f $ENV_FILE_TEMP } diff --git a/plugins/domains/commands b/plugins/domains/commands index e3a9825f6..97f8569cb 100755 --- a/plugins/domains/commands +++ b/plugins/domains/commands @@ -16,19 +16,6 @@ RE_IPV6="${RE_IPV6}fe08:(:[0-9a-fA-F]{1,4}){2,2}%[0-9a-zA-Z]{1,}|" # TEST: f RE_IPV6="${RE_IPV6}::(ffff(:0{1,4}){0,1}:){0,1}${RE_IPV4}|" # TEST: ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses) RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,4}:${RE_IPV4}" # TEST: 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 -domains_restart_app() { - APP="$1"; - - if [[ -f "$DOKKU_ROOT/$APP/CONTAINER" ]]; then - echo "-----> Releasing $APP ..." - dokku release $APP - echo "-----> Release complete!" - echo "-----> Deploying $APP ..." - dokku deploy $APP - echo "-----> Deploy complete!" - fi -} - case "$1" in domains) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 @@ -92,7 +79,7 @@ case "$1" in dokku domains:setup $APP echo "$3" >> "$DOKKU_ROOT/$APP/VHOST" # we need to restart the app to make sure we're binding to the appropriate network interface - domains_restart_app $APP + dokku ps:restart $APP pluginhook post-domains-update $APP echo "-----> Added $3 to $APP" diff --git a/plugins/ps/commands b/plugins/ps/commands new file mode 100755 index 000000000..d0ae01076 --- /dev/null +++ b/plugins/ps/commands @@ -0,0 +1,90 @@ +#!/usr/bin/env bash +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x + +release_and_deploy() { + local APP="$1"; + + if [[ -f "$DOKKU_ROOT/$APP/CONTAINER" ]]; then + echo "-----> Releasing $APP ..." + dokku release $APP + echo "-----> Release complete!" + echo "-----> Deploying $APP ..." + dokku deploy $APP + echo "=====> Application deployed:" + dokku urls $APP | sed "s/^/ /" + echo + fi +} + +case "$1" in + ps) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + [[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1 + + APP="$2"; [[ -f "$DOKKU_ROOT/$APP/CONTAINER" ]] && CONTAINER_ID=$(< "$DOKKU_ROOT/$APP/CONTAINER") + [[ -z "$CONTAINER_ID" ]] && echo "App $APP has not been deployed" && exit 0 + + docker exec -ti "$CONTAINER_ID" /bin/bash -c "ps auxwww" + ;; + + ps:start) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + [[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1 + + APP="$2"; [[ -f "$DOKKU_ROOT/$APP/CONTAINER" ]] && CONTAINER_ID=$(< "$DOKKU_ROOT/$APP/CONTAINER") + [[ -z "$CONTAINER_ID" ]] && echo "App $APP has not been deployed" && exit 0 + + if [[ "$(docker ps -q --no-trunc| grep -q $CONTAINER_ID; echo $?)" != "0" ]]; then + release_and_deploy $APP + else + echo "App $APP already running" + fi + ;; + + ps:stop) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + [[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1 + + APP="$2"; [[ -f "$DOKKU_ROOT/$APP/CONTAINER" ]] && CONTAINER_ID=$(< "$DOKKU_ROOT/$APP/CONTAINER") + [[ -z "$CONTAINER_ID" ]] && echo "App $APP has not been deployed" && exit 0 + + if [[ "$(docker ps -q --no-trunc| grep -q $CONTAINER_ID; echo $?)" = "0" ]]; then + echo "Stopping $APP ..." + docker stop $CONTAINER_ID > /dev/null + else + echo "App $APP already stopped" + fi + ;; + + ps:restart) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + [[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1 + + APP="$2"; [[ -f "$DOKKU_ROOT/$APP/CONTAINER" ]] && CONTAINER_ID=$(< "$DOKKU_ROOT/$APP/CONTAINER") + [[ -z "$CONTAINER_ID" ]] && echo "App $APP has not been deployed" && exit 0 + + release_and_deploy $APP + ;; + + ps:restartall) + for app in $DOKKU_ROOT/*/CONTAINER; do + APP=$(basename "$(dirname $app)"); + dokku ps:restart $APP + done + ;; + + help | ps:help) + cat && cat< List processes running in app container(s) + ps:start Start app container(s) + ps:stop Stop app container(s) + ps:restart Restart app container(s) + ps:restartall Restart all deployed app containers +EOF + ;; + + *) + exit $DOKKU_NOT_IMPLEMENTED_EXIT + ;; + +esac diff --git a/tests/unit/ps.bats b/tests/unit/ps.bats new file mode 100644 index 000000000..53efb0b35 --- /dev/null +++ b/tests/unit/ps.bats @@ -0,0 +1,59 @@ +#!/usr/bin/env bats + +load test_helper + +setup() { + deploy_app +} + +teardown() { + destroy_app +} + +@test "ps" { + # CI support: 'Ah. I just spoke with our Docker expert -- + # looks like docker exec is built to work with docker-under-libcontainer, + # but we're using docker-under-lxc. I don't have an estimated time for the fix, sorry + skip "circleci does not support docker exec at the moment." + run bash -c "dokku ps $TEST_APP | grep -q \"node web.js\"" + echo "output: "$output + echo "status: "$status + assert_success +} + +@test "ps:start" { + run bash -c "dokku ps:stop $TEST_APP" + echo "output: "$output + echo "status: "$status + assert_success + run bash -c "dokku ps:start $TEST_APP" + echo "output: "$output + echo "status: "$status + assert_success + run bash -c "docker ps -q --no-trunc | grep -q $(< $DOKKU_ROOT/$TEST_APP/CONTAINER)" + echo "output: "$output + echo "status: "$status + assert_success +} + +@test "ps:stop" { + run bash -c "dokku ps:stop $TEST_APP" + echo "output: "$output + echo "status: "$status + assert_success + run bash -c "docker ps -q --no-trunc | grep -q $(< $DOKKU_ROOT/$TEST_APP/CONTAINER)" + echo "output: "$output + echo "status: "$status + assert_failure +} + +@test "ps:restart" { + run bash -c "dokku ps:restart $TEST_APP" + echo "output: "$output + echo "status: "$status + assert_success + run bash -c "docker ps -q --no-trunc | grep -q $(< $DOKKU_ROOT/$TEST_APP/CONTAINER)" + echo "output: "$output + echo "status: "$status + assert_success +}