Plugin Creation
Plugins can simply be implementations of triggers or they may implement a command structure of their own. Dokku has no restrictions on the language in which a plugin is implemented, it only cares that the plugin implements the appropriate commands or triggers API. NOTE: all files that implement the triggers or commands API must be executable.
If you create your own plugin:
- Take a look at the plugins shipped with Dokku and hack away!
- Check out the list of triggers your plugin can implement.
- Upload your plugin to github with a repository name in form of
dokku-<name>
(e.g.dokku-mariadb
) - Edit this page and add a link to it.
- Subscribe to the dokku development blog to be notified about API changes and releases
Compilable Plugins (i.e. golang, java(?), c, etc.)
The plugin developer is required to implement the install
trigger such that it will output your built executable(s) in the correct directory structure to implement the plugin's desired command and/or trigger API. See smoke-test-plugin for an example.
Command API
There are 3 main implementation points: commands
, subcommands/default
, and subcommands/<command-name>
commands
Primarily used to supply the plugin's usage/help output. (i.e. plugin help)
subcommands/default
Implements the plugin's default command behavior. (i.e. dokku plugin
)
subcommands/
Implements the additional command interface and will translate to dokku plugin:cmd
on the command line. (i.e. dokku plugin:install
)
Sample plugin
The below plugin is a dummy dokku hello
plugin.
hello/subcommands/default
#!/usr/bin/env bash
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
hello_main_cmd() {
declare desc="prints Hello \$APP"
local cmd="hello"
# Support --app/$DOKKU_APP_NAME flag
# Use the following lines to reorder args into "$cmd $DOKKU_APP_NAME $@""
local argv=("$@")
[[ ${argv[0]} == "$cmd" ]] && shift 1
[[ ! -z $DOKKU_APP_NAME ]] && set -- $DOKKU_APP_NAME $@
set -- $cmd $@
##
[[ -z $2 ]] && dokku_log_fail "Please specify an app to run the command on"
verify_app_name "$2"
local APP="$2";
echo "Hello $APP"
}
hello_main_cmd "$@"
hello/subcommands/world
#!/usr/bin/env bash
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
hello_world_cmd() {
declare desc="prints Hello World"
local cmd="hello:world"
# Support --app/$DOKKU_APP_NAME flag
# Use the following lines to reorder args into "$cmd $DOKKU_APP_NAME $@""
local argv=("$@")
[[ ${argv[0]} == "$cmd" ]] && shift 1
[[ ! -z $DOKKU_APP_NAME ]] && set -- $DOKKU_APP_NAME $@
set -- $cmd $@
##
[[ -z $2 ]] && dokku_log_fail "Please specify an app to run the command on"
verify_app_name "$2"
local APP="$2";
echo "Hello world"
}
hello_world_cmd "$@"
hello/commands
#!/usr/bin/env bash
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
case "$1" in
help | hello:help)
help_content_func () {
declare desc="return help_content string"
cat<<help_content
hello <app>, Says "Hello <app>"
hello:world, Says "Hello world"
help_content
}
if [[ $1 = "hello:help" ]] ; then
echo -e 'Usage: dokku hello[:world] [<app>]'
echo ''
echo 'Say Hello World.'
echo ''
echo 'Example:'
echo ''
echo '$ dokku hello:world'
echo 'Hello world'
echo ''
echo 'Additional commands:'
help_content_func | sort | column -c2 -t -s,
else
help_content_func
fi
;;
*)
exit $DOKKU_NOT_IMPLEMENTED_EXIT
;;
esac
Each plugin requires a plugin.toml
descriptor file with the following required fields:
A few notes:
- Don't forget to
chmod +x
your executable files. - You should always support
DOKKU_TRACE
as specified on the 2nd line of the plugin. - If your command requires that an application exists, ensure you check for it's existence in the manner prescribed above.
- A
help
command is required, though it is allowed to be empty. Also, the command syntax will need to separated by,
in order to maintain columnar output alignment. - Commands should be namespaced.
- As of 0.3.3, a catch-all should be implemented which exits with a
DOKKU_NOT_IMPLEMENTED_EXIT
code. This allows Dokku to output acommand not found
message. -
Be sure you want the "set -eo pipefail" option. Look at the following example :
In the case where the "user/repo" is not installed, Dokku exits just before the awk command, you will never see the message printed with echo. You just want "set -e" in this case.
Here is the documentation of the 'set -eo pipefail' option:
help set
Options:
-e Exit immediately if a command exits with a non-zero status.
-o option-name
pipefail the return value of a pipeline is the status of
the last command to exit with a non-zero status,
or zero if no command exited with a non-zero status
dokku config:set --no-restart node-js-app KEY1=VALUE1 [KEY2=VALUE2 ...]
dokku config:unset --no-restart node-js-app KEY1 [KEY2 ...]
functions
file in your plugin for others to source. Consider all functions in that file to be publicly accessible by other plugins. Any functions not wished to be made "public" should reside within your plugin trigger or commands files.
- As of 0.4.0, we allow image tagging and deployment of said tagged images. Therefore, hard-coding of $IMAGE
as dokku/$APP
is no longer sufficient. Instead, for non pre/post-build-*
plugins, use get_running_image_tag()
& get_app_image_name()
as sourced from common/functions. See the plugin triggers doc for examples.
- As of 0.5.0, we use container labels to help cleanup intermediate containers with dokku cleanup
. If manually calling docker run
, include $DOKKU_GLOBAL_RUN_ARGS
. This will ensure you intermediate containers labeled correctly.
- As of 0.6.0, we advise you to not call the dokku
binary directly from within plugins. Clients using the --app
argument are potentially broken, amongst other issues, when doing so. Instead, please source the functions
file for a given plugin when attempting to call Dokku internal functions