关于 drupal-ddev
drupal-ddev 是一项技能,介绍如何将 DDEV 用作 Drupal 项目的本地开发环境。内容涵盖环境配置、数据库工作流、调试、性能与恢复,并提供专题参考和故障排查指导。
主要功能
- 01配置 Drupal 项目的 DDEV 环境
- 02导入、导出和快照数据库
- 03使用 Drush 与 Xdebug
- 04设置本地 Solr 和自定义命令
- 05排查性能与恢复问题
适用场景
- 01搭建新的或现有的 Drupal 项目
- 02同步或快照项目数据库
- 03诊断缓慢或异常的 DDEV 环境
- 04配置调试工具或本地 Solr
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ grasmash/ drupal-claude-skills --skill drupal-ddev安装后在 Claude Code 中输入/drupal-ddev确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/config-yaml.mdcustom-commands.mddatabase.mdload-and-recovery.mdperformance.mdsolr.mdworkflows.mdxdebug.md详细介绍
用 DDEV 进行 Drupal 开发
全面介绍如何将 DDEV 用作本地 Drupal 开发环境,包括设置、配置、工作流优化和故障排查。
此技能的触发条件
在使用 DDEV 进行本地开发时触发,包括:
- DDEV 配置(.ddev/config.yaml)
- 本地环境设置和管理
- 数据库导入/导出操作
- Drush 集成
- Xdebug 和调试工具
- 性能优化
- 多站点和自定义命令
可用主题
核心设置
- @references/config-yaml.md - .ddev/config.yaml 参考
- @references/workflows.md - 新项目/导入项目设置、远程数据库同步、日常工作流、多项目管理
数据库操作
- @references/database.md - 导入、导出和快照工作流
开发工具
- @references/xdebug.md - 使用 Xdebug 调试
- @references/solr.md - 本地 Solr 搜索设置
高级主题
- @references/custom-commands.md - 创建项目专属命令
- @references/performance.md - 优化 DDEV 性能
- @references/load-and-recovery.md - 主机 CPU 饱和、崩溃后的恢复陷阱、缩减 Mutagen 负载、在临时数据库上运行 Kernel 测试、协调多个 Agent 在同一项目上工作
完整文档请参阅 /references/ 目录。
参考资料
任务需要相关细节时,请阅读对应文件;下方的“常见问题”部分保留在此处,因为几乎每次使用时都会用到。
| 文件 | 适用场景 |
|---|---|
| references/workflows.md | 设置新项目、导入现有项目、从远程环境同步数据库、遵循每日启动/停止流程、管理多个 DDEV 项目,或清理 Agent 的 git worktree 目录 |
| references/performance.md | DDEV 在 macOS 上运行缓慢(Mutagen 与 NFS 的比较)、调整 MariaDB,或 PHPUnit/Kernel 运行缓慢(快速引导、最小测试范围、Kernel 测试套件的运行位置) |
| references/xdebug.md | 开启/关闭 Xdebug,或将 IDE(VSCode launch.json)连接到 Xdebug |
| references/custom-commands.md | 在 .ddev/commands/web/ 下编写项目专属的 ddev <command> |
| references/config-yaml.md | 编辑 .ddev/config.yaml,且超出下方基本示例所涵盖的范围(PHP、数据库、端口、主机名、钩子、服务、环境变量) |
| references/database.md | 导入、导出、创建快照、访问或清理数据库,或数据库导入失败 |
| references/solr.md | 为 Search API 运行本地 Solr 服务 |
| references/load-and-recovery.md | 主机负载过高时请求挂起、Docker 崩溃后、缩减 Mutagen 负载、针对临时数据库运行 Kernel 测试,或多个 Agent 共用一个 DDEV 项目 |
快速参考
必备命令
# Start project
ddev start
# Stop project
ddev stop
# Restart services
ddev restart
# SSH into web container
ddev ssh
# Run Drush commands
ddev drush cr
ddev drush status
ddev drush config:status
# Run Composer
ddev composer require drupal/module_name
ddev composer update
# Database operations
ddev import-db --file=backup.sql.gz
ddev export-db --file=backup.sql.gz
ddev snapshot
# View logs
ddev logs
ddev logs -f # Follow mode
# Describe project
ddev describe
# Access URLs
ddev launch # Open site in browser
基本的 .ddev/config.yaml
name: myproject
type: drupal11
docroot: web
php_version: "8.3"
webserver_type: nginx-fpm
database:
type: mariadb
version: "10.6"
nodejs_version: "24"
# Additional services
additional_services:
- solr
# Custom upload/execution limits
upload_dirs:
- web/sites/default/files
# Performance settings
performance_mode: mutagen # For macOS
最佳实践
- 提交 .ddev/config.yaml - 与团队共享配置
- 使用 ddev composer,而不是本地 composer
- 不要提交数据库快照 - 文件太大
- 执行高风险操作前创建快照
- 不调试时禁用 Xdebug - 避免影响性能
- 在 macOS 上使用 mutagen - 文件同步速度快得多
- 定期运行 ddev poweroff - 释放系统资源
- 固定服务版本 - PHP、数据库、Node.js
- 使用钩子实现自动化 - 执行启动后任务
- 记录自定义命令 - 帮助团队成员
常见问题
站点无法加载
# Restart project
ddev restart
# Check status
ddev describe
# View logs
ddev logs
# Clear Drupal cache
ddev drush cr
数据库连接错误
# Check database is running
ddev describe
# Verify settings.php or settings.ddev.php exists
ddev ssh
ls web/sites/default/settings*.php
端口冲突
# Stop all DDEV projects
ddev poweroff
# Check for port conflicts
lsof -i :80 -i :443
# Change router HTTP port if needed
ddev config --router-http-port=8080 --router-https-port=8443
macOS 上性能缓慢
# Enable mutagen
ddev config --performance-mode=mutagen
ddev restart
# Or use NFS
ddev config --nfs-mount-enabled=true
ddev restart
Drush 中的 PHP 弃用警告
如果运行 Drush 命令时出现 PHP 弃用警告(尤其是在 PHP 8.4 中),请创建自定义 PHP 配置文件来屏蔽这些警告:
.ddev/php/drush.ini:
; Suppress PHP deprecation warnings for Drush commands
[PHP]
error_reporting = 22527
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /tmp/php-errors.log
然后重启 DDEV:
ddev restart
工作原理:
error_reporting = 22527等同于E_ALL & ~E_DEPRECATEDdisplay_errors = Off可防止警告显示在 STDERR 上display_startup_errors = Off可屏蔽引导阶段的警告- 错误会记录到
/tmp/php-errors.log,而不是直接显示
此配置同时适用于 Web 和 CLI 环境,因为 DDEV 会将 .ddev/php/*.ini 文件复制到 /etc/php/[version]/cli/conf.d/ 和 /etc/php/[version]/fpm/conf.d/。
中断的 ddev composer install 会留下幽灵安装包(补丁从未应用)
如果 ddev composer install/update 在运行中被终止(Docker 因 OOM 以状态码 137 退出、主机超时或崩溃),Composer 可能已在终止前将软件包记录为已安装,因此下一次运行 composer install 时会提示 “Nothing to install, update or remove”,而 composer-patches 也不会应用该软件包的补丁。结果是一个只完成部分构建的 contrib 目录树,导致看似不可能出现的运行时错误(例如 DI ServiceCircularReferenceException、因未打补丁的构造函数导致的 TypeError);修复目录树后,这些错误便不会再出现。
诊断:
# Verify patch application (a verify-patches script if your project has one,
# or spot-check a known-patched file in the vendored tree)
ddev composer install # says "Nothing to install" despite the missing patches
修复——强制干净地重新安装受影响的软件包(重新应用其补丁):
ddev composer reinstall drupal/<pkg>
规则:在任何 Composer 运行中断后,都应将整个软件包目录树视为可疑。重新安装运行中被处理的软件包,重新验证补丁,然后再调试剩余错误——在目录树损坏期间看到的错误可能已经消失。检查错误日志的时间戳:在着手修复之前,确认致命错误现在仍可复现。
超时终止的 ddev drush 命令会遗留容器内进程
终止主机端的 ddev drush ... 进程(Ctrl-C、工具超时)并不会终止 Web 容器内的 PHP 进程。这些孤儿进程会不断累积、争抢 CPU,导致之后每次 Drush 引导都变得极其缓慢(drush cr/updb/updatedb:status 需要 10 分钟以上——看起来像是卡住,实际上是资源耗尽)。
诊断/清理:
ddev exec "ps aux | grep -v grep | grep -E 'vendor/bin/drush|php /var/www'"
ddev exec "pkill -f 'vendor/bin/drush'"
两个推论:
- 长时间运行的 Drush 操作(大型升级时的
updb、冷启动cr)只运行一次,并在后台执行,设置充足的超时时间——不要反复尝试较短的运行时限;每次终止都会增加一个孤儿进程。 - “卡住后被终止”的
updb可能已经完成了实际工作——更新钩子会逐个记录。重新运行或慌张之前,先检查实际执行了什么:
ddev mysql -e "SELECT value FROM key_value WHERE collection='system.schema' AND name='<module>'"
ddev mysql -N -e "SELECT value FROM key_value WHERE collection='post_update' AND name='existing_updates'" | grep -o "<module>_post_update_[a-z0-9_]*"
Docker Engine 卡死(对 DDEV 反复排查前先检查)
phpunit 以状态码 137 退出、后台任务在运行中死亡、ddev exec 再次触发完整的镜像重建,或每次 ddev start 都提示“container name already in use”——这些看起来像是 DDEV 的问题,但往往是仍驻留的应用进程使 Docker Desktop engine 崩溃所致。请先检查:
timeout 5 docker version # hangs on the Server section -> engine is dead
docker ps # if this responds while `docker version` hangs, engine is wedged
修复:运行 killall -9 com.docker.backend && open -a Docker,轮询 docker ps 直到命令有响应,然后运行 ddev start。如果 engine 本身已停止,就不要继续尝试修复 ddev 层面的问题(poweroff/mutagen reset 等)——这些方法都无法奏效。重启后,留意孤儿容器和首次运行 Drush 缓慢的问题:崩溃后的陷阱。
主机 CPU 饱和(容器正常,但请求挂起)
主机负载远高于核心数;容器运行正常,且 php -v 会立即返回,但每个请求和 Drush 引导都挂起(php-fpm 工作进程阻塞在停滞的 virtiofs 桥接上,处于 request_wait_answer 状态)。在负载下降之前,任何 DDEV 恢复操作都无法解决问题——先降低负载,然后运行一次 ddev poweroff && ddev start。详情请参阅:load-and-recovery.md。
恢复后出现 404 和路由发现警告
恢复操作(Docker 重启、mutagen 重置、核心更新)后立即出现 404 和路由发现警告,且 ddev drush cr 无法修复,这通常是 APCu 中的编译容器过期:即使数据库中的 cache_container 是最新的,php-fpm 的操作码缓存仍保留着更改前的代码。修复方法:docker restart ddev-<project>-web(强制刷新 APCu)——不要再次清除缓存。
容器状态显示正常,但路由器 TLS 连接重置
即使 ddev describe 显示一切正常,且 docker ps 显示 ddev-router 运行正常,对 https://<project>.ddev.site 执行 curl 仍会立即失败并返回退出代码 35(TLS 握手期间“Connection reset by peer”)。应用本身没有问题——是路由器卡住了。
区分应用和路由器的问题(完全绕过路由器):
ddev exec "curl -s -o /dev/null -w '%{http_code}' http://localhost/<path>"
修复方法:
docker restart ddev-router
Docker Desktop overlay2 I/O 错误
如果 Docker Desktop 进入异常状态,产生 overlay2 或 containerd I/O 错误,例如:
Error response from daemon: error creating temporary lease: write /var/lib/desktop-containerd/daemon/io.containerd.metadata.v1.bolt/meta.db: input/output error
Error response from daemon: open /var/lib/docker/overlay2/...: input/output error
正常退出并重启 Docker Desktop 并不足以解决问题。必须强制退出所有 Docker 进程(通过“活动监视器”或运行 killall -9 Docker / killall -9 com.docker.hyperkit),然后重新启动 Docker Desktop。只有彻底强制退出才能清除损坏状态。
“readdirent bad message”变体:这表示虚拟机磁盘在容器元数据层面已损坏,并非暂时性的 overlay2 故障——反复运行 ddev start 无法修复。应隔离损坏容器的元数据目录,而不是反复重启(通过 nsenter 进入 alpine 容器,并将有问题的 /var/lib/docker/containers/<id> 目录移到一旁)。
容器运行不正常 / Mutagen 同步卡住
Docker 崩溃或被强制退出后,DDEV 可能进入异常状态,出现以下情况:
ddev start卡在“Starting Mutagen sync process...”- Web 容器报告运行不正常(
phpstatus:FAILED、mailpit:FAILED) ddev mutagen reset失败并显示“CreateOrResumeMutagenSync Failure”
修复方法(按顺序运行):
# 1. Full power off to clean up all containers and networks
ddev poweroff
# 2. Start fresh
ddev start
如果 ddev poweroff 未能解决问题:
# 1. Stop DDEV
ddev stop
# 2. Reset the Mutagen daemon
~/.ddev/bin/mutagen daemon stop
~/.ddev/bin/mutagen daemon start
# 3. Reset Mutagen sync (removes Docker volume, forces full resync)
ddev mutagen reset
# 4. Start fresh
ddev start
排查问题时使用的监控命令:
ddev mutagen status -l # Detailed sync status
ddev mutagen monitor # Real-time sync progress
docker inspect --format "{{ json .State.Health }}" ddev-<project>-web # Container health
磁盘用量:不要相信 ls 或 du
ls -la 报告的是稀疏文件(例如 Docker.raw)的逻辑大小,可能远大于磁盘上的实际占用空间;由于会重复计算快照之间共享的写时复制克隆,du 在 APFS 上会高估用量。这两个命令都无法回答“此操作实际上会占用或释放多少空间”。只相信操作前后立即获取的 df 差值。
相关技能
- @drupal-config-mgmt - 配置管理工作流
- @drupal-contrib-mgmt - 使用 Composer 管理模块
- @drupal-at-your-fingertips - Drupal 通用模式
官方文档:https://ddev.readthedocs.io Drupal DDEV 快速入门:https://ddev.readthedocs.io/en/stable/users/quickstart/ 社区支持:https://discord.gg/5wjP76mBJD