Custom Commands¶
Custom commands can easily be added to DDEV, to be executed on the host or in containers.
This involves adding a Bash script to the project in .ddev/commands/host
, a specific container in .ddev/commands/<containername>
, or globally in ~/.ddev/commands
.
Example commands in ddev/commands/*/*.example
can be copied, moved, or symlinked.
For example, .ddev/commands/host/mysqlworkbench.example can be used to add a ddev mysqlworkbench
command. Rename it from mysqlworkbench.example
to mysqlworkbench
. If you’re on macOS or Linux (or some configurations of Windows) you can cd .ddev/commands/host && ln -s mysqlworkbench.example mysqlworkbench
.
The ddev mysql
runs the mysql
client inside the db
container command using this technique. See the ddev mysql
command.
Notes for All Command Types¶
- The command filename is not what determines the name of the command. That comes from the “Usage” doc line (
## Usage: commandname
). - To confirm that your custom command is available, run
ddev -h
and look for it in the list.
Host Commands¶
To provide host commands, place a Bash script in .ddev/commands/host
. For example, a PhpStorm launcher to make the ddev phpstorm
command might go in .ddev/commands/host/phpstorm
with these contents. The OSTypes
and HostBinaryExists
annotations are optional, but are useful to prevent the command from showing up if it’s not useful to the user.
#!/usr/bin/env bash
## Description: Open PhpStorm with the current project
## Usage: phpstorm
## Example: "ddev phpstorm"
## OSTypes: darwin
## HostBinaryExists: "/Applications/PhpStorm.app"
# Example is macOS-specific, but easy to adapt to any OS
open -a PhpStorm.app ${DDEV_APPROOT}
Container Commands¶
To provide a command which will execute in a container, add a Bash script to .ddev/commands/<container_name>
, for example, .ddev/commands/web/mycommand
. The Bash script will be executed inside the named container. For example, see the several standard DDEV script-based web container commands.
You can run commands in custom containers as well as standard DDEV web
and db
containers. Use the service name, like .ddev/commands/solr/<command>
. The only catch with a custom container is that your service must mount /mnt/ddev_config
like the web
and db
containers do; the volumes
section of docker-compose.<servicename>.yaml
needs:
For example, to add a solrtail
command that runs in a Solr service, add .ddev/commands/solr/solrtail
with:
#!/bin/bash
## Description: Tail the main solr log
## Usage: solrtail
## Example: ddev solrtail
tail -f /opt/solr/server/logs/solr.log
Global Commands¶
Global commands work exactly the same as project-level commands, but they need to go in your global .ddev
directory. Your home directory has a .ddev/commands
in it, where you can add host, web, or db commands.
Changes to the command files in the global .ddev
directory need a ddev start
for changes to be picked up by a project, as the global commands are copied to the project on start.
Shell Command Examples¶
There are many examples of global and project-level custom/shell commands that ship with DDEV you can adapt for your own use. They can be found in your ~/.ddev/commands/*
directories and in your project’s .ddev/commands/*
directories. There you’ll see how to provide usage, examples, and how to use arguments provided to the commands. For example, the xdebug
command shows simple argument processing and the launch command demonstrates flag processing.
Environment Variables Provided¶
A number of environment variables are provided to these command scripts. These are generally supported, but please avoid using undocumented environment variables. Useful variables for host scripts are:
DDEV_APPROOT
: File system location of the project on the hostDDEV_DATABASE
: Database in use, in formattype:version
(example:mariadb:10.5
)DDEV_DATABASE_FAMILY
: Database “family” (example:mysql
,postgres
), useful for database connection URLsDDEV_DOCROOT
: Relative path from approot to docrootDDEV_GID
: The GID the web container runs asDDEV_HOSTNAME
: Comma-separated list of FQDN hostnamesDDEV_HOST_DB_PORT
: Localhost port of the database serverDDEV_HOST_HTTPS_PORT
: Localhost port for HTTPS on web serverDDEV_HOST_MAILPIT_PORT
: Localhost port for MailpitDDEV_HOST_WEBSERVER_PORT
: Localhost port of the web serverDDEV_MAILPIT_HTTP_PORT
: Router Mailpit port for HTTPDDEV_MAILPIT_HTTPS_PORT
: Router Mailpit port for HTTPSDDEV_MUTAGEN_ENABLED
:true
if Mutagen is enabledDDEV_PHP_VERSION
: Current PHP versionDDEV_PRIMARY_URL
: Primary project URLDDEV_PROJECT
: Project name, liked8composer
DDEV_PROJECT_TYPE
:drupal8
,typo3
,backdrop
,wordpress
, etc.DDEV_ROUTER_HTTP_PORT
: Router port for HTTPDDEV_ROUTER_HTTPS_PORT
: Router port for HTTPSDDEV_SITENAME
: Project name, liked8composer
DDEV_TLD
: Top-level project domain, likeddev.site
DDEV_UID
: The UID the web container runs asDDEV_WEBSERVER_TYPE
:nginx-fpm
,apache-fpm
, ornginx-gunicorn
GOARCH
: Architecture (arm64
,amd64
)GOOS
: Operating system (windows
,darwin
,linux
)
Useful variables for container scripts are:
DDEV_DOCROOT
: Relative path from approot to docrootDDEV_FILES_DIR
: Deprecated, first directory of user-uploaded filesDDEV_FILES_DIRS
: Comma-separated list of directories of user-uploaded filesDDEV_HOSTNAME
: Comma-separated list of FQDN hostnamesDDEV_MUTAGEN_ENABLED
:true
if Mutagen is enabledDDEV_PHP_VERSION
: Current PHP versionDDEV_PRIMARY_URL
: Primary URL for the projectDDEV_PROJECT
: Project name, liked8composer
DDEV_PROJECT_TYPE
:drupal8
,typo3
,backdrop
,wordpress
, etc.DDEV_ROUTER_HTTP_PORT
: Router port for HTTPDDEV_ROUTER_HTTPS_PORT
: Router port for HTTPSDDEV_SITENAME
: Project name, liked8composer
DDEV_TLD
: Top-level project domain, likeddev.site
DDEV_WEBSERVER_TYPE
:nginx-fpm
,apache-fpm
, ornginx-gunicorn
IS_DDEV_PROJECT
: Iftrue
, PHP is running under DDEV
Annotations Supported¶
Custom commands support various annotations in the header for providing additional information to the user.
“Description” Annotation¶
Description
should briefly describe the command in its help message.
Usage: ## Description: <command-description>
Example: ## Description: my great custom command
“Usage” Annotation¶
Usage
should explain how to use the command in its help message.
Usage: ## Usage: <command-usage>
Example: ## Usage: commandname [flags] [args]
“Example” Annotation¶
Example
should demonstrate how the command might be used. Use \n
to force a line break.
Usage: ## Example: <command-example>
Example: ## Example: commandname\ncommandname -h
“Flags” Annotation¶
Flags
should explain any available flags, including their shorthand when relevant, for the help message. It has to be encoded according the following definition:
If no flags are specified, the command will have its flags parsing disabled. Global flags like --help
will not work unless the command supports them.
You can still do ddev help <command>
to see the command’s provided usage help.
Usage: ## Flags: <json-definition>
This is the minimal usage of a flags definition:
Example: ## Flags: [{"Name":"flag","Usage":"sets the flag option"}]
Output:
Multiple flags are separated by a comma:
Example: ## Flags: [{"Name":"flag1","Shorthand":"f","Usage":"flag1 usage"},{"Name":"flag2","Usage":"flag2 usage"}]
Output:
The following fields can be used for a flag definition:
Name
: the name as it appears on command lineShorthand
: one-letter abbreviated flagUsage
: help messageType
: possible values arebool
,string
,int
,uint
(defaults tobool
)DefValue
: default value for usage messageNoOptDefVal
: default value, if the flag is on the command line without any optionsAnnotations
: used by cobra.Command Bash autocomplete code (see https://github.com/spf13/cobra/blob/main/site/content/completions/bash.md)
“CanRunGlobally” Annotation¶
This annotation is only available for global host commands.
Use CanRunGlobally: true
if your global host command can be safely run even if the current working directory isn’t inside a DDEV project.
This will make your command available to run regardless of what your current working directory is when you run it.
This annotation will have no effect if you are also using one of the following annotations:
ProjectTypes
DBTypes
Example: ## CanRunGlobally: true
“ProjectTypes” Annotation¶
If your command should only be visible for a specific project type, ProjectTypes
will allow you to define the supported types. This is especially useful for global custom commands. See Quickstart for many CMSes for more information about the supported project types. Multiple types are separated by a comma.
Usage: ## ProjectTypes: <list-of-project-types>
Example: ## ProjectTypes: drupal7,drupal8,drupal9,backdrop
“OSTypes” Annotation (Host Commands Only)¶
If your host command should only run on one or more operating systems, add the OSTypes
annotation. Multiple types are separated by a comma. Valid types are:
darwin
for macOSwindows
for Windowslinux
for Linux
Usage: ## OSTypes: <list-of-os-types>
Example: ## OSTypes: darwin,linux
“HostBinaryExists” Annotation (Host Commands Only)¶
If your host command should only run if a particular file exists, add the HostBinaryExists
annotation.
Usage: ## HostBinaryExists: <path/to/file>
Example: ## HostBinaryExists: /Applications/Sequel ace.app
“DBTypes” Annotation¶
If your command should only be available for a particular database type, add the DBTypes
annotation. Multiple types are separated by a comma. Valid types the available database types.
Usage: ## DBTypes: <type>
Example: ## DBTypes: postgres
“HostWorkingDir” Annotation (Container Commands Only)¶
If your container command should run from the directory you are running the command in the host, add the HostWorkingDir
annotation.
Example: ## HostWorkingDir: true
“ExecRaw” Annotation (Container Commands Only)¶
Use ExecRaw: true
to pass command arguments directly to the container as-is.
For example, when ExecRaw
is true, ddev yarn --help
returns the help for yarn
, not DDEV’s help for the ddev yarn
command.
We recommend using this annotation for all container commands. The default behavior is retained to avoid breaking existing commands.
Example: ## ExecRaw: true
Known Windows Issues¶
Line Endings¶
If you’re editing a custom command to be run in a container, it must have LF line endings and not traditional Windows CRLF line endings. Remember that a custom command in a container is a script that must execute in a Linux environment.
Bash¶
Commands can’t be executed if DDEV can’t find bash
. If you’re running inside Git Bash in most any terminal, this shouldn’t be an issue, and DDEV should be able to find git-bash
if it’s in C:\Program Files\Git\bin
as well. But if neither of those is true, add the directory of bash.exe
to your PATH
environment variable.