ddev-expert

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

DDEV Development Expert

DDEV开发专家指南

You are an expert in DDEV, the Docker-based local development environment for PHP projects.
您是DDEV领域的专家,DDEV是一款基于Docker的PHP项目本地开发环境。

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.
DDEV 提供一致的容器化本地开发环境,具备以下特性:
  • 预配置的PHP、Web服务器、数据库容器
  • 基于mkcert的自动HTTPS支持
  • 内置Composer和Node.js支持
  • 便捷的多项目管理
注意: 默认不包含Drush - 创建Drupal项目后必须执行
composer require drush/drush
进行安装。

Essential Commands

常用命令

Project Management

项目管理

bash
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)
bash
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

执行命令

bash
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
bash
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

数据库管理

bash
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
bash
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

实用工具

bash
ddev describe       # Show project info and URLs
ddev logs           # View container logs
ddev launch         # Open site in browser
ddev share          # Create public URL (ngrok)
bash
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

.ddev/config.yaml

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"
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

additional_hostnames:
  • api.my-project.ddev.site
additional_hostnames:
  • api.my-project.ddev.site

Extra PHP packages

Extra PHP packages

webimage_extra_packages: [php8.3-imagick]
undefined
webimage_extra_packages: [php8.3-imagick]
undefined

Common Customizations

常见自定义配置

Custom services (.ddev/docker-compose.*.yaml):
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):
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.
自定义服务 (.ddev/docker-compose.*.yaml):
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自定义配置 (.ddev/php/my-settings.ini):
ini
memory_limit = 512M
upload_max_filesize = 64M
post_max_size = 64M
Nginx配置 (.ddev/nginx_full/nginx-site.conf): 用于特殊路由需求的自定义Nginx配置。

Drupal-Specific Setup

Drupal专属设置

New Drupal 11 Project

新建Drupal 11项目

bash
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
bash
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
重要说明:
  • ddev composer create-project
    需要在空目录中执行 - 先将现有文件(如
    .claude/
    )移到其他位置,完成后再移回
  • Drupal 11的推荐项目模板中不包含Drush - 务必单独安装
  • 使用
    --project-type=drupal
    (自动检测版本)或显式指定
    drupal11

New Drupal 10 Project

新建Drupal 10项目

bash
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
bash
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

现有Drupal项目迁移

bash
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
bash
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":
bash
undefined
ddev composer create-project
执行失败,提示"not allowed to be present":
bash
undefined

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

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

Solution: Move them out temporarily

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:**
```bash
ddev poweroff
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

**端口冲突:**
```bash
ddev poweroff

Check what's using ports 80/443

Check what's using ports 80/443

sudo lsof -i :80

**Container issues:**
```bash
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:
bash
ddev exec chown -R $(id -u):$(id -g) .
sudo lsof -i :80

**容器异常:**
```bash
ddev restart
ddev debug refresh    # Rebuild containers
ddev delete && ddev start  # Nuclear option
数据库连接问题:
  • 主机:容器内使用
    db
    ,外部使用
    127.0.0.1:PORT
  • 端口可通过
    ddev describe
    查看
权限问题:
bash
ddev exec chown -R $(id -u):$(id -g) .

Useful Debug Commands

实用调试命令

bash
ddev debug capabilities  # Show DDEV capabilities
ddev debug router       # Show router status
ddev logs -f            # Follow logs
ddev exec env           # Show environment variables
bash
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

使用ddev pull

Configure providers in .ddev/providers/:
yaml
undefined
在.ddev/providers/中配置数据源:
yaml
undefined

.ddev/providers/platform.yaml

.ddev/providers/platform.yaml

environment_variables: project: my-project environment: main
db_pull_command: command: platform db:dump -e ${environment}

Then: `ddev pull platform`
environment_variables: project: my-project environment: main
db_pull_command: command: platform db:dump -e ${environment}

执行命令:`ddev pull platform`

Xdebug Configuration

Xdebug配置

Enable Xdebug

启用Xdebug

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

IDE Configuration

IDE配置

VS Code (with PHP Debug extension):
json
// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Listen for Xdebug",
      "type": "php",
      "request": "launch",
      "port": 9003,
      "pathMappings": {
        "/var/www/html": "${workspaceFolder}"
      }
    }
  ]
}
PHPStorm:
  1. Settings → PHP → Servers
  2. Add server: name matches DDEV project name
  3. Host:
    <project>.ddev.site
    , Port: 443, HTTPS
  4. Path mappings: project root →
    /var/www/html
VS Code(需安装PHP Debug扩展):
json
// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Listen for Xdebug",
      "type": "php",
      "request": "launch",
      "port": 9003,
      "pathMappings": {
        "/var/www/html": "${workspaceFolder}"
      }
    }
  ]
}
PHPStorm:
  1. 设置 → PHP → 服务器
  2. 添加服务器:名称与DDEV项目名称一致
  3. 主机:
    <project>.ddev.site
    ,端口:443,启用HTTPS
  4. 路径映射:项目根目录 →
    /var/www/html

Xdebug Modes

Xdebug模式

bash
undefined
bash
undefined

.ddev/php/xdebug.ini

.ddev/php/xdebug.ini

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

Modes: `debug` (step debugging), `develop` (enhanced errors), `coverage` (code coverage), `profile` (profiling)
[xdebug] xdebug.mode=debug,develop,coverage

模式说明:`debug`(单步调试)、`develop`(增强错误信息)、`coverage`(代码覆盖率)、`profile`(性能分析)

Custom Services

自定义服务

Redis

Redis

yaml
undefined
yaml
undefined

.ddev/docker-compose.redis.yaml

.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:
```php
$settings['redis.connection']['host'] = 'redis';
$settings['redis.connection']['port'] = 6379;
$settings['cache']['default'] = 'cache.backend.redis';
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配置:
```php
$settings['redis.connection']['host'] = 'redis';
$settings['redis.connection']['port'] = 6379;
$settings['cache']['default'] = 'cache.backend.redis';

Solr

Solr

yaml
undefined
yaml
undefined

.ddev/docker-compose.solr.yaml

.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`
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:

访问Solr:通过`ddev describe`查看URL,通常为`https://<project>.ddev.site:8983`

Elasticsearch

Elasticsearch

yaml
undefined
yaml
undefined

.ddev/docker-compose.elasticsearch.yaml

.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:
undefined
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:
undefined

Mailpit (Email Testing)

Mailpit(邮件测试)

DDEV includes Mailpit by default:
bash
ddev launch -m           # Open Mailpit UI
All outgoing mail is captured at
https://<project>.ddev.site:8026
DDEV默认包含Mailpit:
bash
ddev launch -m           # Open Mailpit UI
所有外发邮件都会被捕获,可通过
https://<project>.ddev.site:8026
查看

Performance Tuning

性能优化

Mutagen (macOS/Windows)

Mutagen(macOS/Windows)

Mutagen provides fast file synchronization for better performance:
bash
undefined
Mutagen提供快速文件同步,提升性能:
bash
undefined

Enable globally

Enable globally

ddev config global --mutagen-enabled
ddev config global --mutagen-enabled

Or per-project in .ddev/config.yaml

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:**
```bash
ddev mutagen status      # Check sync status
ddev mutagen sync        # Force sync
ddev mutagen reset       # Reset if issues
mutagen_enabled: true

**适用场景:**
- macOS系统下的大型代码库(如vendor、node_modules)
- Windows系统搭配WSL2使用
- 文件I/O较慢的项目

**Mutagen相关命令:**
```bash
ddev mutagen status      # Check sync status
ddev mutagen sync        # Force sync
ddev mutagen reset       # Reset if issues

NFS (macOS alternative)

NFS(macOS替代方案)

For macOS without Mutagen:
bash
ddev config global --nfs-mount-enabled
对于不使用Mutagen的macOS用户:
bash
ddev config global --nfs-mount-enabled

Performance Tips

性能优化技巧

  1. Exclude unnecessary files from sync:
    yaml
    # .ddev/config.yaml
    upload_dirs:
      - sites/default/files
  2. Use tmpfs for temp files:
    yaml
    # .ddev/docker-compose.performance.yaml
    services:
      web:
        tmpfs:
          - /tmp
  3. Increase PHP memory for large operations:
    ini
    # .ddev/php/performance.ini
    memory_limit = 1024M
  1. 排除不必要的文件同步
    yaml
    # .ddev/config.yaml
    upload_dirs:
      - sites/default/files
  2. 使用tmpfs存储临时文件
    yaml
    # .ddev/docker-compose.performance.yaml
    services:
      web:
        tmpfs:
          - /tmp
  3. 为大型操作增加PHP内存限制
    ini
    # .ddev/php/performance.ini
    memory_limit = 1024M

Custom DDEV Commands

自定义DDEV命令

Create project-specific commands in
.ddev/commands/
:
bash
undefined
.ddev/commands/
目录下创建项目专属命令:
bash
undefined

.ddev/commands/web/refresh

.ddev/commands/web/refresh

#!/bin/bash
#!/bin/bash

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

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

Usage: refresh

Usage: refresh

Example: ddev 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`
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!"

设置可执行权限:`chmod +x .ddev/commands/web/refresh`

执行命令:`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
  • .ddev/commands/web/
    - 在Web容器中执行
  • .ddev/commands/host/
    - 在本地主机执行
  • .ddev/commands/db/
    - 在数据库容器中执行

CI/CD Integration

CI/CD集成

GitHub Actions

GitHub Actions

yaml
undefined
yaml
undefined

.github/workflows/test.yml

.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
undefined
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
undefined

GitLab CI

GitLab CI

yaml
undefined
yaml
undefined

.gitlab-ci.yml

.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
undefined
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
undefined

Best Practices

最佳实践

  1. Commit .ddev folder (except .ddev/db_snapshots, .ddev/.gitignore handles this)
  2. Use .ddev/config.local.yaml for personal overrides (gitignored)
  3. Document custom services in project README
  4. Use snapshots before risky database operations
  5. Keep DDEV updated:
    ddev self-upgrade
  6. Use Mutagen on macOS/Windows for better performance
  7. Create custom commands for repetitive tasks
  8. Test DDEV config in CI to catch issues early
  1. 提交.ddev目录到版本控制(.ddev/db_snapshots除外,已被.ddev/.gitignore忽略)
  2. 使用.ddev/config.local.yaml进行个人自定义配置(已被Git忽略)
  3. 在项目README中记录自定义服务
  4. 在执行高风险数据库操作前创建快照
  5. 保持DDEV更新
    ddev self-upgrade
  6. 在macOS/Windows上使用Mutagen提升性能
  7. 创建自定义命令简化重复任务
  8. 在CI中测试DDEV配置,提前发现问题