How DDEV Works¶
DDEV is a Go application that stores its configuration in files on your workstation.
It uses those blueprints to mount your project files into Docker containers that facilitate the operation of a local development environment.
DDEV writes and uses docker-compose files for you, which is a detail you can cheerfully ignore unless you’re Docker-curious or defining your own services.
Directory Tour¶
DDEV stores configuration in two places: a single .ddev
directory in your home folder (can be moved to another location), and a .ddev
directory for each project you set up.
The global configuration directory is used to keep track of your projects and any of the global settings that apply across all projects. You’ll probably spend more time working with the per-project .ddev
directories for their configuration and overrides.
Project Files¶
A project’s .ddev
directory can be intimidating at first, so let’s take a look at what lives in there.
Yours May Differ Slightly
You may have some directories or files that aren’t listed here, likely added by custom services.
For example, if you see a solr
directory, it probably pertains to a custom Solr add-on service.
addon-metadata
directory- Contains metadata about add-on services that have been added to the project. This allows commands like
ddev get --installed
andddev get --remove
to work, see Managing Installed Add-Ons. apache
directory- Default Apache configuration when using
webserver_type: apache-fpm
, which can be customized. commands
subdirectories- Project custom shell commands that can run on the host or inside a container.
config.yaml
- The project’s main configuration file.
config.*.yaml
files- Environmental overrides for parts of
config.yaml
. db-build
directory- Can be used to provide a custom Dockerfile for the database container.
db_snapshots
directory- Where snapshots go when you run the
ddev snapshot
command. You can safely delete anything in here that you don’t need. docker-compose.*.yaml
files- Where Docker-friendly users can provide their own custom compose files that add or override services. Read more in Additional Service Configurations & Add-ons and check out examples in ddev-contrib.
homeadditions
directory- Files to be copied into the web container on startup. You could use this, for example, to override the default home directory contents (
.profile
,.bashrc
,.composer
,.ssh
), or include scripts that you’d like to be available inside the container. (You can do the same thing globally in~/.ddev/homeadditions
.) Check out the homeadditions docs for more. mutagen
directory- Contains
mutagen.yml
, where you can override the default Mutagen configuration. mysql
directory- Contains optional
mysql
ormariadb
configuration. nginx
directory- Can be used for add-on nginx snippets.
nginx_full
directory- Contains the nginx configuration used by the web container, which can be customized.
postgres
directory- Contains
postgresql.conf
, which can be edited if needed. Remove the#ddev-generated
line at the top to take it over. providers
directory- Contains examples and implementations to demonstrate how the
ddev pull
command can work with hosting providers. traefik
directory- Configures the
ddev-router
when it is using Traefik. web-build
directory- Can be used to provide a custom Dockerfile for the web container.
web-entrypoint.d
directory- Custom scripts (named
*.sh
) in this directory will be run during web container startup, before the php-fpm server or other daemons are run. This can be useful, for example, for introducing environment variables into the context of the nginx and php-fpm servers. Use this carefully, because custom entrypoints can very easily break things. xhprof
directory- Contains the
xhprof_prepend.php
file that can be used to customize xhprof behavior for different types of websites.
Hidden Project Files¶
Files beginning with .
are hidden because they shouldn’t be fiddled with; most are regenerated, and thus overwritten, on every ddev start
:
.dbimageBuild
directory- The generated Dockerfile used to customize the
db
container on first start. .ddev-docker-compose-base.yaml
- The base docker-compose file used to describe a project.
.ddev-docker-compose-full.yaml
- The result of preprocessing
.ddev-docker-compose-base.yaml
usingdocker-compose config
. Mostly it replaces environment variables with their values. .gitignore
- The
.gitignore
is generated by DDEV and should generally not be edited or checked in. (It gitignores itself to make sure you don’t check it in.) It’s generated on everyddev start
and will change as DDEV versions change, so if you check it in by accident it will always be showing changes that you don’t need to see ingit status
. .homeadditions
- Temporary directory used to consolidate global
homeadditions
with project-levelhomeadditions
. You shouldn’t ever have to look here. .webimageBuild
directory- The generated Dockerfile used to customize the web container on first start.
Global Files¶
There’s only one global .ddev
directory, which normally lives in your home directory: ~/.ddev
($HOME/.ddev
) or in ~/.config/ddev
. ~/.ddev
takes precedence if it exists, unless $XDG_CONFIG_HOME
is set, in which case it will be $XDG_CONFIG_HOME/ddev
.
Where is my global .ddev
config?
Use ddev version
(look at global-ddev-dir
) to check which location is used for the .ddev
global directory.
What if I don’t want to clutter up my $HOME
with a .ddev
directory?
DDEV can use the $XDG_CONFIG_HOME
environment variable from XDG Base Directory Specification to move ~/.ddev
to the $XDG_CONFIG_HOME/ddev
directory if $XDG_CONFIG_HOME
is defined:
ddev poweroff
# permanently set environment variable using a directory that works for you
export XDG_CONFIG_HOME="$HOME/.config"
# restart the terminal and run:
mv ~/.ddev ${XDG_CONFIG_HOME}/ddev
Otherwise, on Linux/WSL2 only, the default $HOME/.config/ddev
can be used when ~/.config/ddev
exists and ~/.ddev
does not exist. You can move the config directory with:
global_config.yaml
- This YAML file defines your global configuration, which consists of various config settings.
project_list.yaml
- This YAML file defines your project list that lets DDEV keep track of the projects you’ve added.
bin
directory- This is where DDEV stores private executable binaries it needs, like
mutagen
anddocker-compose
. commands
directory- Directory for storing DDEV commands that should be available in containers, like
npm
,artisan
,cake
anddrush
for example. These are organized in subdirectories named for where they’ll be used:db
,host
, andweb
. You can add your own custom commands here. homeadditions
directory- Like the per-project
homeadditions
directory, files you add here will automatically be copied into the web container’s home directory. Files from the global homeadditions directory will be copied into every web container’s home directory.
Hidden Global Files¶
Again, these files are mostly regenerated on every ddev start
so it’s best to leave them alone:
.gitignore
- Prevents files from getting checked in when they shouldn’t be.
.router-compose-full.yaml
- The complete, generated docker-compose directive used for DDEV’s router.
.router-compose.yaml
- The base docker-compose directive used in generating
.router-compose-full.yaml
. router-compose.*.yaml
docker-compose
files with the namerouter-compose.*.yaml
can be used to override stanzas in the.router-compose.yaml
file..ssh-auth-compose-full.yaml
- The complete, generated docker-compose directive used for DDEV’s SSH agent.
.ssh-auth-compose.yaml
- The base docker-compose directive used in generating
.ssh-auth-compose-full.yaml
. .sshimageBuild
- Directory used for storing DDEV’s generated
Dockerfile
used in building the SSH agent image. .update
- An empty file whose purpose is mysterious and intriguing.
.ddev_mutagen_data_directory
DDEV uses a global ~/.ddev_mutagen_data_directory
for storing Mutagen sync data.
Container Architecture¶
It’s easiest to think of DDEV as a set of little networked computers (Docker containers) that are in a different network from your workstation but still reachable from it.
When you install or upgrade DDEV you’re mostly installing a single ddev
binary. When you use it, it downloads the Docker images it needs, and then starts them based on what’s needed for your projects.
- The
ddev-webserver
container (one per project) runsnginx
orapache
andphp-fpm
for a single site, so it does all the basic work of a PHP-interpreting web server. - The
ddev-dbserver
container (one per project) handles MariaDB/MySQL/PostgreSQL database management. It can be reached from the web server by the hostnamedb
or with the more explicit nameddev-<projectname>-db
. - Additional add-on services may be there for a given project, for example
phpmyadmin
,solr
,elasticsearch
, ormemcached
.
Although it’s not common usage, different projects can communicate with each other as described in the FAQ.
Now for the two oddball global containers (there’s only one of each):
- The
ddev-router
container is a “reverse proxy”. It takes incoming HTTP/S requests, looks up the hostname in the incoming URL, and routes it to the correct project’sddev-webserver
. Depending on the project’s configuration withadditional_hostnames
andadditional_fqdns
, it can route many different URLs to a single project’sddev-webserver
. If, like most people, you use the named URLs likehttps://something.ddev.site
, your request goes through the router. When you use the127.0.0.1
URLs, the requests go directly to theddev-webserver
. - The
ddev-ssh-agent
container runs anssh-agent
inside the Docker network so that after runddev auth ssh
all the different projects can use your SSH keys for outgoing requests—like private Composer access or SCP from a remote host.
Here’s a basic diagram of how it works inside the Docker network: