ddev-expert

DDEV Development Expert

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ddev-expert" with this command: npx skills add madsnorgaard/agent-resources/madsnorgaard-agent-resources-ddev-expert

DDEV Development Expert

You are an expert in DDEV, the Docker-based local development environment for PHP projects.

Core Concepts

DDEV provides a consistent, containerized local development environment with:

  • Pre-configured PHP, web server, database containers

  • Automatic HTTPS with mkcert

  • Built-in Composer and Node.js support

  • Easy multi-project management

Note: Drush is NOT included by default - you must composer require drush/drush after creating a Drupal project.

Essential Commands

Project Management

ddev start # Start project containers ddev stop # Stop project containers ddev restart # Restart containers ddev poweroff # Stop all DDEV projects ddev delete # Remove project (keeps files)

Executing Commands

ddev drush <cmd> # Run Drush commands ddev composer <cmd> # Run Composer ddev php <script> # Run PHP scripts ddev exec <cmd> # Run any command in web container ddev ssh # SSH into web container

Database

ddev mysql # MySQL CLI ddev export-db # Export database ddev import-db # Import database (--file=dump.sql) ddev snapshot # Create database snapshot ddev restore # Restore from snapshot

Utilities

ddev describe # Show project info and URLs ddev logs # View container logs ddev launch # Open site in browser ddev share # Create public URL (ngrok)

Configuration

.ddev/config.yaml

name: my-project type: drupal # Auto-detects Drupal version, or use drupal11/drupal10 docroot: web php_version: "8.3" # Use 8.3 for Drupal 11, 8.2 for Drupal 10 webserver_type: nginx-fpm database: type: mariadb version: "10.11"

Additional hostnames

additional_hostnames:

  • api.my-project.ddev.site

Extra PHP packages

webimage_extra_packages: [php8.3-imagick]

Common Customizations

Custom services (.ddev/docker-compose.*.yaml):

version: '3.6' services: redis: image: redis:7 container_name: ddev-${DDEV_SITENAME}-redis labels: com.ddev.site-name: ${DDEV_SITENAME} expose: - "6379"

PHP overrides (.ddev/php/my-settings.ini):

memory_limit = 512M upload_max_filesize = 64M post_max_size = 64M

Nginx config (.ddev/nginx_full/nginx-site.conf): Custom nginx configuration for special routing needs.

Drupal-Specific Setup

New Drupal 11 Project

mkdir my-drupal && cd my-drupal ddev config --project-type=drupal --docroot=web --php-version=8.3 ddev start ddev composer create-project drupal/recommended-project:^11 ddev composer require drush/drush ddev drush site:install --account-name=admin --account-pass=admin -y ddev launch

Important notes:

  • ddev composer create-project requires a clean directory - move any existing files (like .claude/ ) out first, then move them back after

  • Drush is NOT included in Drupal 11's recommended-project - always install it separately

  • Use --project-type=drupal (auto-detects version) or explicitly drupal11

New Drupal 10 Project

mkdir my-drupal && cd my-drupal ddev config --project-type=drupal --docroot=web --php-version=8.2 ddev start ddev composer create-project drupal/recommended-project:^10 ddev composer require drush/drush ddev drush site:install --account-name=admin --account-pass=admin -y ddev launch

Existing Drupal Project

cd existing-project ddev config --project-type=drupal --docroot=web ddev start ddev composer install ddev import-db --file=database.sql.gz ddev drush cr

Troubleshooting

Common Issues

ddev composer create-project fails with "not allowed to be present":

This happens when extra directories exist (like .claude/, .git/, etc.)

Solution: Move them out temporarily

mv .claude /tmp/claude-backup mv .git /tmp/git-backup ddev composer create-project drupal/recommended-project:^11 mv /tmp/claude-backup .claude mv /tmp/git-backup .git

Port conflicts:

ddev poweroff

Check what's using ports 80/443

sudo lsof -i :80

Container issues:

ddev restart ddev debug refresh # Rebuild containers ddev delete && ddev start # Nuclear option

Database connection issues:

  • Host: db (inside container) or 127.0.0.1:PORT (outside)

  • Check port with ddev describe

Permission issues:

ddev exec chown -R $(id -u):$(id -g) .

Useful Debug Commands

ddev debug capabilities # Show DDEV capabilities ddev debug router # Show router status ddev logs -f # Follow logs ddev exec env # Show environment variables

Multi-Environment Workflows

Using ddev pull

Configure providers in .ddev/providers/:

.ddev/providers/platform.yaml

environment_variables: project: my-project environment: main

db_pull_command: command: platform db:dump -e ${environment}

Then: ddev pull platform

Xdebug Configuration

Enable Xdebug

ddev xdebug on # Enable step debugging ddev xdebug off # Disable (faster performance) ddev xdebug status # Check current state

IDE Configuration

VS Code (with PHP Debug extension):

// .vscode/launch.json { "version": "0.2.0", "configurations": [ { "name": "Listen for Xdebug", "type": "php", "request": "launch", "port": 9003, "pathMappings": { "/var/www/html": "${workspaceFolder}" } } ] }

PHPStorm:

  • Settings → PHP → Servers

  • Add server: name matches DDEV project name

  • Host: <project>.ddev.site , Port: 443, HTTPS

  • Path mappings: project root → /var/www/html

Xdebug Modes

.ddev/php/xdebug.ini

[xdebug] xdebug.mode=debug,develop,coverage

Modes: debug (step debugging), develop (enhanced errors), coverage (code coverage), profile (profiling)

Custom Services

Redis

.ddev/docker-compose.redis.yaml

services: redis: image: redis:7-alpine container_name: ddev-${DDEV_SITENAME}-redis labels: com.ddev.site-name: ${DDEV_SITENAME} com.ddev.approot: $DDEV_APPROOT expose: - "6379" volumes: - redis-data:/data

volumes: redis-data:

Drupal settings.php:

$settings['redis.connection']['host'] = 'redis'; $settings['redis.connection']['port'] = 6379; $settings['cache']['default'] = 'cache.backend.redis';

Solr

.ddev/docker-compose.solr.yaml

services: solr: image: solr:9 container_name: ddev-${DDEV_SITENAME}-solr labels: com.ddev.site-name: ${DDEV_SITENAME} com.ddev.approot: $DDEV_APPROOT expose: - "8983" volumes: - solr-data:/var/solr command: solr-precreate drupal

volumes: solr-data:

Access Solr: ddev describe shows URL, typically https://<project>.ddev.site:8983

Elasticsearch

.ddev/docker-compose.elasticsearch.yaml

services: elasticsearch: image: elasticsearch:8.11.0 container_name: ddev-${DDEV_SITENAME}-elasticsearch labels: com.ddev.site-name: ${DDEV_SITENAME} com.ddev.approot: $DDEV_APPROOT environment: - discovery.type=single-node - xpack.security.enabled=false - "ES_JAVA_OPTS=-Xms512m -Xmx512m" expose: - "9200" volumes: - elasticsearch-data:/usr/share/elasticsearch/data

volumes: elasticsearch-data:

Mailpit (Email Testing)

DDEV includes Mailpit by default:

ddev launch -m # Open Mailpit UI

All outgoing mail is captured at https://<project>.ddev.site:8026

Performance Tuning

Mutagen (macOS/Windows)

Mutagen provides fast file synchronization for better performance:

Enable globally

ddev config global --mutagen-enabled

Or per-project in .ddev/config.yaml

mutagen_enabled: true

When to use Mutagen:

  • macOS with large codebases (vendor, node_modules)

  • Windows with WSL2

  • Projects with slow file I/O

Mutagen commands:

ddev mutagen status # Check sync status ddev mutagen sync # Force sync ddev mutagen reset # Reset if issues

NFS (macOS alternative)

For macOS without Mutagen:

ddev config global --nfs-mount-enabled

Performance Tips

Exclude unnecessary files from sync:

.ddev/config.yaml

upload_dirs:

  • sites/default/files

Use tmpfs for temp files:

.ddev/docker-compose.performance.yaml

services: web: tmpfs: - /tmp

Increase PHP memory for large operations:

.ddev/php/performance.ini

memory_limit = 1024M

Custom DDEV Commands

Create project-specific commands in .ddev/commands/ :

.ddev/commands/web/refresh

#!/bin/bash

Description: Full site refresh (db + config + cache)

Usage: refresh

Example: ddev refresh

set -e

echo "Importing database..." drush sql:drop -y drush sql:cli < /var/www/html/reference.sql

echo "Importing config..." drush config:import -y

echo "Running updates..." drush updatedb -y

echo "Clearing cache..." drush cache:rebuild

echo "Done!"

Make executable: chmod +x .ddev/commands/web/refresh

Then run: ddev refresh

Command Locations

  • .ddev/commands/web/

  • Run in web container

  • .ddev/commands/host/

  • Run on host machine

  • .ddev/commands/db/

  • Run in database container

CI/CD Integration

GitHub Actions

.github/workflows/test.yml

name: Tests on: [push, pull_request]

jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4

  - name: Setup DDEV
    uses: ddev/github-action-setup-ddev@v1

  - name: Start DDEV
    run: ddev start

  - name: Install dependencies
    run: ddev composer install

  - name: Run tests
    run: ddev exec ./vendor/bin/phpunit

GitLab CI

.gitlab-ci.yml

test: image: ddev/ddev-gitpod-base:latest services: - docker:dind variables: DOCKER_HOST: tcp://docker:2375 script: - ddev start - ddev composer install - ddev exec ./vendor/bin/phpunit

Best Practices

  • Commit .ddev folder (except .ddev/db_snapshots, .ddev/.gitignore handles this)

  • Use .ddev/config.local.yaml for personal overrides (gitignored)

  • Document custom services in project README

  • Use snapshots before risky database operations

  • Keep DDEV updated: ddev self-upgrade

  • Use Mutagen on macOS/Windows for better performance

  • Create custom commands for repetitive tasks

  • Test DDEV config in CI to catch issues early

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

drupal-expert

No summary provided by upstream source.

Repository SourceNeeds Review
Security

drupal-security

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

drupal-migration

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

docker-local

No summary provided by upstream source.

Repository SourceNeeds Review