Drupal 9本地开发最佳实践:DDEV+Docker一站式环境搭建
1. 项目概述为什么本地用 Docker DDEV 搭建 Drupal 9 环境是当前最稳的开发起点你是不是也经历过这样的场景刚接手一个 Drupal 9 项目团队给了一堆composer.json、settings.php和.ddev配置但你的本地环境要么 PHP 版本不对Drupal 9.5 要求 PHP 8.0要么 MySQL 版本太老不支持 JSON 字段要么 Apache 模块没开全mod_rewrite、mod_headers 缺一不可折腾半天drush cr报错、/admin页面白屏、甚至composer install直接卡死在symfony/yaml的扩展检测上我试过在 macOS 上手动编译 PHP 8.2、在 Windows WSL2 里反复重装 MariaDB、也在 Ubuntu 22.04 上被php-sqlite3扩展缺失坑了整整一个下午——直到我把整套环境交给 DDEV Docker才真正把“环境问题”从每日待办清单里划掉。这个标题直指一个非常具体、高频、且极具实操价值的技术组合Drupal 9 本地开发 Docker 容器化 DDEV 工具链。它不是泛泛而谈“如何学 Drupal”而是精准锁定“如何让 Drupal 9 在你自己的笔记本上像生产环境一样可靠、可复现、可协作地跑起来”。关键词Drupal 9决定了技术栈边界PHP 8.0–8.2、MySQL 5.7/MariaDB 10.3、Apache/Nginx mod_rewriteDocker是底层虚拟化基石解决“系统依赖隔离”这一根本矛盾DDEV则是面向 Drupal及 WordPress、TYPO3 等 PHP CMS深度优化的开发平台它把 Docker 的复杂性封装成几条命令同时内置了 Drupal 专用的调试钩子、数据库同步、文件共享策略和 HTTPS 代理。而entornos locales本地环境这个西班牙语词恰恰点明了核心诉求不依赖远程服务器、不依赖同事的配置、不依赖公司统一镜像——你的电脑就是生产环境的最小可信副本。适合谁看如果你是刚从 Drupal 7 升级过来的开发者对 Composer 依赖管理还不熟如果你是前端工程师需要快速拉起后端环境联调 Twig 模板和 REST API如果你是运维新手想理解容器化如何替代传统 LAMP 堆栈甚至如果你是项目经理需要向客户解释“为什么我们开发环境必须和线上一致”——这篇文章都给你准备好了可验证、可截图、可复现的完整路径。接下来所有内容全部基于真实项目落地经验从零安装、首次启动、模块启用、多语言配置到排查502 Bad Gateway、修复vendor/autoload.php not found、绕过国内网络限制拉取镜像——没有理论空谈只有键盘敲出来的每一步。2. 整体设计思路为什么放弃 MAMP/XAMPP/Laragon坚定选择 DDEV Docker2.1 不是“又一种本地环境工具”而是为 Drupal 量身定制的开发协议很多人第一次看到 DDEV会下意识把它和 MAMP、Laragon 或 XAMPP 归为一类——都是“点开图标就能跑 PHP”的本地套件。这是最大的误解。MAMP 是把 Apache、PHP、MySQL 打包进一个 macOS 应用XAMPP 是 Windows 下的类似方案它们本质仍是进程级共存PHP 进程跑在宿主机上MySQL 数据库文件存在 C:\xampp\mysql\data 里所有服务共享同一套系统库。而 DDEV 的底层是 Docker这意味着每个项目拥有独立的、不可变的运行时环境你的 Drupal 9 项目用 PHP 8.1 MySQL 8.0 Nginx隔壁的 Laravel 项目用 PHP 8.2 PostgreSQL 14 Apache它们互不干扰哪怕你同时启动十个 DDEV 项目资源占用也远低于一个 MAMP 实例。环境定义即代码Infrastructure as Code.ddev/config.yaml文件明确声明了 PHP 版本、Web 服务器类型、数据库类型、端口映射、自定义命令等。这个文件可以提交到 Git新同事git clone ddev start就能获得和你完全一致的环境——而 MAMP 的配置藏在图形界面里无法版本化。Drupal 深度集成是刚需不是锦上添花DDEV 内置了ddev drush、ddev drush sql:sync、ddev drush cim等命令它知道 Drupal 的webroot在web/还是docroot/能自动识别settings.local.php并注入开发配置如禁用缓存、开启错误报告甚至能一键生成drush别名供远程同步使用。MAMP 只提供一个空白 PHP 环境你要自己配 Drush、自己写settings.local.php、自己处理trusted_host_patterns——这些在 DDEV 里全是开箱即用。提示DDEV 的核心价值不是“比 MAMP 多了 Docker”而是它把 Drupal 开发中那些重复、易错、难协作的环境配置动作全部标准化、自动化、可审计化。当你在.ddev/config.yaml里写下php_version: 8.1你不是在选一个版本而是在签署一份环境契约从此这个项目的 PHP 行为将严格遵循 PHP 8.1 的 RFC 规范包括str_contains()函数是否存在、match表达式语法是否合法、以及DateTime::createFromImmutable()是否可用——这些细节直接决定你的模块能否通过 Drupal 9.5 的兼容性检查。2.2 Docker 为何不可替代从三个真实故障说起有人问“我的 Mac 已经装了 Homebrew PHP 8.1为什么还要 Docker” 我用三个项目现场故障回答故障一PHP 扩展冲突项目 A 要求gd扩展带 WebP 支持项目 B 要求imagick扩展用 ImageMagick 7。Homebrew 只能全局安装一个php-gd你改一次brew reinstall php8.1 --with-webp项目 B 就报Class Imagick not found。Docker 中每个项目镜像都预装好所需扩展ddev/php-8.1-webp镜像含 WebPddev/php-8.1-imagemagick含 Imagick切换只需改一行php_version配置。故障二MySQL 字符集陷阱Drupal 9 默认要求utf8mb4字符集但 macOS 自带的 MySQL 5.7 默认collation_serverutf8mb4_unicode_ci而某些旧版 Drupal 模块如pathauto的 SQL 查询会因utf8mb4的索引长度限制失败。你在宿主机上改my.cnf可能影响其他项目在 Docker 里DDEV 的mysql服务镜像已预设character-set-serverutf8mb4和collation-serverutf8mb4_unicode_ci且innodb_large_prefixON开箱即合规。故障三Composer 依赖地狱drupal/core-recommended要求symfony/http-foundation:^5.4但你的全局 Composer 用的是^6.0。宿主机上composer update会报冲突DDEV 中ddev composer命令在容器内执行使用的是镜像内置的 Composer 2.5 和精确匹配的 Symfony 版本vendor/目录完全隔离不会污染宿主机。注意DDEV 的 Docker 镜像不是通用 Linux 发行版而是专为 PHP CMS 优化的精简镜像。它去掉了apt-get update、systemd、cron等无关组件只保留apache2,nginx,php-fpm,mysql-client,drush,composer等必需项。这使得镜像体积小PHP 8.1 镜像仅 280MB、启动快平均 3.2 秒、内存占用低空闲时 120MB。你不需要成为 Docker 专家但必须理解DDEV 的价值始于 Docker 提供的确定性成于它对 Drupal 场景的深度适配。2.3 DDEV vs Lando vs Docksal为什么选 DDEV市场上还有 Lando 和 Docksal 两个同类工具。我对比过它们在 Drupal 9 项目中的实际表现维度DDEVLandoDocksalDrupal 9 原生支持✅ 内置drush,drupal,ddev drush命令自动识别webroot和settings.php⚠️ 需手动配置services和toolingDrupal 9 的trusted_host_patterns需额外写.lando.yml⚠️ 依赖finCLIDrupal 9 的composer install常因权限问题失败Windows 兼容性✅ 原生支持 Windows 10/11WSL2 或 Docker Desktopddev start无报错❌ WSL2 下需额外配置host: trueHTTPS 证书常失效⚠️ 强制要求 WSL2Docker Desktop 安装步骤复杂国内镜像支持✅ddev config global --use-docker-compose-file可指定国内镜像源ddev get插件市场有ddev-contrib/ddev-drupal9预配置⚠️ 镜像源需手动修改.lando.yml无官方中文文档❌ 无国内镜像支持拉取docksal/cli镜像常超时调试体验✅ddev xdebug一键开启VS Code 的PHP Debug扩展可直接断点index.php⚠️ Xdebug 需手动配置xdebug.modedebug和xdebug.client_host⚠️ Xdebug 配置分散在多个文件新手易配错结论很清晰如果你的目标是最快、最稳、最少配置地让 Drupal 9 在本地跑起来并长期维护多个 Drupal 项目DDEV 是目前唯一一个把“Drupal 开发者体验”做到产品级的工具。它不追求 Docker 技术炫技而是把 90% 的常见问题HTTPS、邮件发送、数据库导入、文件上传封装成一条命令让你专注写模块、调样式、测 API。3. 核心细节解析DDEV 配置文件、目录结构与 Drupal 9 专属约定3.1.ddev/config.yaml的每一行都在解决什么问题DDEV 的灵魂是.ddev/config.yaml。这不是一个可有可无的配置文件而是整个本地环境的“宪法”。我们逐行拆解一个典型的 Drupal 9 项目配置# .ddev/config.yaml name: my-drupal-site type: drupal9 docroot: web php_version: 8.1 webserver_type: nginx-fpm database: mariadb:10.6 use_dns_when_possible: true additional_fqdns: [] router_http_port: 80 router_https_port: 443 xdebug_enabled: false web_environment: []name: my-drupal-site项目唯一标识DDEV 用它生成容器名如ddev-my-drupal-site-web、数据库名db、以及 HTTPS 证书域名my-drupal-site.ddev.site。命名不能含下划线_否则 Docker 会报错invalid container name。type: drupal9这是最关键的字段。它告诉 DDEV“请按 Drupal 9 的最佳实践初始化环境”。DDEV 会自动创建settings.local.php并注入error_level ERROR_REPORTING_DISPLAY_ALL设置trusted_host_patterns为[^my\-drupal\-site\.ddev\.site$]启用opcache.revalidate_freq0禁用 OPCache 缓存配置 Nginx 的location ~ \.php$块正确传递SCRIPT_FILENAME。如果你写type: phpDDEV 就不会做这些 Drupal 专属操作你得自己手写settings.local.php和 Nginx 配置。docroot: webDrupal 9 推荐的目录结构composer create-project drupal/recommended-project生成Web 根目录是web/子目录而非项目根目录。DDEV 会把web/挂载为 Web 服务器的DocumentRoot。如果项目是旧版 Drupaldocroot/或根目录这里要改成docroot或.。php_version: 8.1DDEV 支持 PHP 7.4–8.2但 Drupal 9.5强制要求 PHP 8.0。选8.1是因为它是 Drupal 9.5 的最低推荐版本兼容所有核心模块8.2虽新但部分第三方模块如devel4.x尚未完全适配8.0已 EOLEnd of Life安全更新已停止。webserver_type: nginx-fpmNginx PHP-FPM 组合比 Apache 更轻量DDEV 的 Nginx 配置已针对 Drupal 9 优化包含try_files $uri /index.php?$query_string和fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name完美支持 Clean URLs。database: mariadb:10.6MariaDB 10.6 是 Drupal 9.5 的推荐数据库它原生支持JSON字段config表存储、utf8mb4_0900_as_cs排序规则区分大小写且性能优于 MySQL 5.7。DDEV 的mariadb:10.6镜像已预设character-set-serverutf8mb4和collation-serverutf8mb4_unicode_ci。实操心得每次新建项目我必做的三件事是①ddev config --project-typedrupal9 --docrootweb --php-version8.1自动生成配置②ddev start启动后立即ddev exec drush status确认Drupal version和PHP configuration显示正确③ddev describe查看所有服务端口和 URL确保https://my-drupal-site.ddev.site可访问。这三步能在 2 分钟内验证环境基础是否健康。3.2 目录结构为什么web/是黄金标准Drupal 9 推荐的目录结构如下由composer create-project drupal/recommended-project生成my-drupal-site/ ├── composer.json # 项目依赖定义 ├── web/ # Web 根目录必须 │ ├── index.php # Drupal 入口 │ ├── sites/ # settings.php, modules/, themes/ │ └── core/ # Drupal 核心由 Composer 管理 ├── vendor/ # Composer 依赖不应提交 Git └── .ddev/ # DDEV 配置这个结构的价值在于彻底分离 Web 可访问目录与项目源码web/是唯一被 Web 服务器公开的目录index.php在此sites/default/files上传目录在此robots.txt和.htaccess也在此。攻击者即使拿到 Web Shell也无法直接读取项目根目录下的composer.json含敏感配置或.ddev/config.yaml含数据库密码。core/、vendor/、.ddev/等目录位于web/之外Web 服务器默认禁止访问DDEV 的 Nginx 配置已添加location ~ ^/(vendor|core|modules|themes|profiles|libraries|includes|misc|scripts|sites|templates|web|README|CHANGELOG|INSTALL|LICENSE|MAINTAINERS)\b { deny all; }。sites/default/settings.php中的$settings[hash_salt]和数据库连接信息应放在sites/default/settings.local.php由 DDEV 自动生成并 Git 忽略避免泄露。提示如果你的旧项目是扁平结构index.php在项目根目录迁移至web/结构只需三步①mkdir web mv index.php .htaccess robots.txt web/②mv core/ modules/ profiles/ sites/ themes/ web/③ 修改web/sites/default/settings.php中的$settings[hash_salt]路径将../改为../../。DDEV 会自动识别web/并挂载为根目录无需改 Nginx 配置。3.3 Drupal 9 专属配置settings.local.php里的生存指南DDEV 在web/sites/default/settings.local.php中注入的配置是 Drupal 9 本地开发的“安全气囊”。我们来解读关键行// web/sites/default/settings.local.php $databases[default][default] [ database db, username db, password db, host db, port 3306, driver mysql, prefix , ]; $settings[hash_salt] ...; // DDEV 自动生成的随机盐值 $settings[container_yamls][] DRUPAL_ROOT . /sites/development.services.yml; $config[system.performance][css][preprocess] FALSE; $config[system.performance][js][preprocess] FALSE; $settings[error_level] ERROR_REPORTING_DISPLAY_ALL; $settings[php_storage][default][directory] /tmp; $settings[skip_permissions_hardening] TRUE;$databases数组host设为db是因为 DDEV 的数据库服务容器名就是dbDocker 内部 DNS 会自动解析db为数据库容器 IP。你不需要记127.0.0.1或localhostDDEV 已为你做好服务发现。$settings[error_level] ERROR_REPORTING_DISPLAY_ALL强制显示所有 PHP 错误、警告、通知包括E_DEPRECATED弃用警告。Drupal 9 正在逐步淘汰mysql_*函数这个设置能让你第一时间发现模块兼容性问题。$config[system.performance][*][preprocess] FALSE禁用 CSS/JS 聚合确保你修改theme.css后刷新即生效不用清缓存。$settings[skip_permissions_hardening] TRUEDDEV 的文件挂载机制bind mount在 Windows/macOS 上常导致chmod权限错误此设置跳过 Drupal 的权限加固检查避免The file permissions could not be set on ...报错。$settings[php_storage][default][directory] /tmp将 PHP OPcache、Twig 编译缓存等临时文件存到容器/tmp目录而非宿主机sites/default/files避免 Windows/macOS 文件系统权限问题。注意settings.local.php不应提交到 Git。DDEV 的.gitignore已包含web/sites/*/settings.local.php。如果你在团队中应确保所有成员都运行ddev start由 DDEV 自动创建该文件。手动编辑它可能导致环境不一致。4. 实操过程从零开始搭建、启动、配置 Drupal 9 本地环境4.1 环境准备Docker Desktop 与 DDEV 的安装要点Docker Desktop 安装Windows/macOSWindows必须 Windows 10 Pro/Enterprise 22H2Build 19045或 Windows 11。Home 版本不支持 WSL2无法运行 DDEV。下载 Docker Desktop for Windows 安装时勾选“Enable the WSL 2 based engine”。安装后重启打开 PowerShell 运行wsl -l -v确认 WSL2 已启用。macOSIntel 芯片用 Docker Desktop for Mac (Intel) Apple SiliconM1/M2用 Docker Desktop for Mac (ARM64) 。安装后在 Docker Desktop 设置中开启“Use the new Virtualization framework”macOS 13.3 必须开启。LinuxUbuntu/Debian不推荐 Docker Desktop直接用apt安装 Docker Enginesudo apt update sudo apt install -y ca-certificates curl gnupg lsb-release sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo usermod -aG docker $USER提示Linux 用户务必运行sudo usermod -aG docker $USER并重新登录否则ddev会报Permission denied while trying to connect to the Docker daemon socket。DDEV 安装macOSHomebrewbrew tap drud/ddev brew install ddevWindowsChocolateychoco install ddevLinux/通用curl -LO https://raw.githubusercontent.com/drud/ddev/master/scripts/install_ddev.sh bash install_ddev.sh验证安装ddev version应输出DDEV-Local version v1.22.4或更高docker version应显示Client和Server版本均正常。实操心得我遇到最多的安装失败90% 是 Docker Desktop 未启动或 WSL2 未启用。Windows 用户务必在 PowerShell 中运行wsl -l -v确认状态为RunningmacOS 用户在 Docker Desktop 图标右键菜单中确认 “Start Docker Desktop” 已勾选。不要跳过这一步否则ddev start会卡在Starting services...。4.2 创建 Drupal 9 项目Composer 初始化与 DDEV 初始化步骤 1用 Composer 创建标准 Drupal 9 项目# 创建项目目录 mkdir my-drupal-site cd my-drupal-site # 使用 Drupal 推荐项目模板Drupal 9.5 composer create-project drupal/recommended-project . # 等待完成约 3–5 分钟国内用户建议先配置 Composer 镜像 # 完成后目录结构为./web/, ./vendor/, ./composer.json 等提示国内用户 Composer 拉取慢务必提前配置阿里云镜像composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/这能将composer create-project时间从 15 分钟缩短至 3 分钟。步骤 2初始化 DDEV 配置# 在项目根目录运行 ddev config --project-typedrupal9 --docrootweb --php-version8.1 # 输出 # Created a new ddev project configuration in the current directory # Configuration file written to .ddev/config.yaml # You can now run ddev start to start your site.此时.ddev/config.yaml已生成内容如前文所述。DDEV 还会自动创建.ddev/.gitignore忽略db.sql.gz等敏感文件。步骤 3启动环境ddev start # 输出 # Starting my-drupal-site... # Network ddev-default created # Creating ddev-my-drupal-site-db ... done # Creating ddev-my-drupal-site-web ... done # Creating ddev-my-drupal-site-dba ... done # Successfully started my-drupal-site # Project can be reached at https://my-drupal-site.ddev.site https://127.0.0.1:32772 # You can run ddev describe to get more information步骤 4验证环境健康# 查看服务状态 ddev describe # 输出关键信息 # NAME STATUS URLS # my-drupal-site Running https://my-drupal-site.ddev.site # https://127.0.0.1:32772 # 进入 Web 容器执行 Drush ddev exec drush status # 输出应包含 # Drupal version : 9.5.13 # Site URI : https://my-drupal-site.ddev.site # Database driver : mysql # Database hostname : db # Database port : 3306 # Database username : db # Database name : db # PHP configuration : /etc/php/8.1/fpm/php.ini # PHP OS : Linux # Drush script : /var/www/html/vendor/drush/drush/drush # Drush version : 11.5.1注意如果ddev exec drush status报错Command drush not found说明vendor/bin/drush未生成。运行ddev composer install重新安装依赖。DDEV 的composer命令在容器内执行确保使用正确的 PHP 版本。4.3 安装 Drupal 9浏览器安装与命令行安装双路径浏览器安装推荐新手打开浏览器访问https://my-drupal-site.ddev.siteDDEV 会自动重定向到https://my-drupal-site.ddev.site/install.php选择语言点击“Save and continue”数据库配置页面Database name:dbDatabase username:dbDatabase password:dbDatabase host:db不是localhostDatabase port:3306点击“Save and continue”等待安装完成设置站点信息站点名称、管理员邮箱、用户名、密码完成安装。命令行安装推荐 CI/CD 或批量部署# 生成一次性安装命令替换 YOUR_SITE_NAME, ADMIN_EMAIL, ADMIN_PASS ddev exec drush site:install standard \ --site-nameMy Drupal Site \ --account-nameadmin \ --account-passadmin123 \ --account-mailadminexample.com \ --localeen \ --yes # 输出 # Installation complete. User name: admin User password: admin123 # Congratulations, you installed Drupal!提示命令行安装后ddev exec drush uli可生成一次性登录链接如https://my-drupal-site.ddev.site/user/reset/1/1698765432/abc123def456ghi789jkl012mno345pqr678stu901vwx234yz567...点击即可免密登录比记密码更安全。4.4 日常开发操作模块启用、主题切换、数据库同步启用模块以 Devel 模块为例# 1. 用 Composer 安装模块自动处理依赖 ddev composer require drupal/devel:^4.0 # 2. 启用模块Drush 命令 ddev exec drush en devel devel_generate -y # 3. 清除缓存 ddev exec drush cr切换主题以 Olivero 主题为例# 1. 启用 OliveroDrupal 9.4 默认主题 ddev exec drush theme:enable olivero # 2. 设为默认主题 ddev exec drush config:set system.theme default olivero # 3. 清除缓存 ddev exec drush cr数据库同步从生产环境拉取最新数据# 1. 在生产环境导出数据库假设生产环境也用 DDEV # ssh into production server, then: ddev export-db --fileprod-db.sql.gz # 2. 将 prod-db.sql.gz 复制到本地项目根目录 # 3. 导入到本地数据库 ddev import-db --srcprod-db.sql.gz # 4. 更新文件同步 sites/default/files ddev rsync --src:/var/www/html/web/sites/default/files/ --destweb/sites/default/files/实操心得ddev import-db会自动解压.sql.gz并执行mysql -u db -pdb db file.sql。它比手动gunzipmysql更可靠因为 DDEV 知道数据库容器名和凭据。文件同步用ddev rsync而非rsync命令是因为它能正确处理 Docker 容器内的路径映射。5. 常见问题与排查技巧实录从启动失败到模块报错的实战手册5.1 启动失败ddev start卡在Starting services...现象ddev start执行后终端停在Starting services...无报错10 分钟后超时。排查步骤检查 Docker 是否运行Windows/macOS确认 Docker Desktop 图标在任务栏/菜单栏右键显示 “Docker Desktop is running”。Linuxsudo systemctl status docker确认active (running)。检查端口占用DDEV 默认用80和443端口。运行lsof -i :80macOS/Linux或netstat -ano | findstr :80Windows查看是否有其他程序如 IIS、Apache占用了端口。若有ddev config --router-http-port8080 --router-https-port8443修改端口。检查 WSL2 磁盘空间Windowswsl -l -v确认 WSL2 分发版状态wsl -d Ubuntu-22.04进入后运行df -h若/分区使用率 100%需清理~/.docker或运行wsl --shutdown后重启。提示我遇到过三次ddev start卡住两次是 Docker Desktop 未启动图标灰了一次是 WSL2 磁盘满/var/lib/docker占用 20GB。记住ddev poweroff是万能重启键它会停止所有 DDEV 容器比docker-compose down更彻底。5.2 访问白屏https://my-drupal-site.ddev.site显示空白页现象浏览器打开 URL页面空白无错误Network 面板显示200 OK但 Response 为空。排查步骤检查 PHP 错误日志ddev logs -s web # 查找 PHP Fatal error 或 PHP Parse error检查 Drupal 日志ddev exec drush watchdog:show --limit10 # 或查看 web/sites/default/files/php://stderr典型原因与修复vendor/autoload.php not foundcomposer install未执行。运行ddev composer install。settings.php not foundweb/sites/default/settings.php权限错误。运行ddev exec chmod 644 web/sites/default/settings.php。Trusted Host Settings报错settings.php中trusted_host_patterns未匹配域名。DDEV 已自动注入但如果你手动改过运行ddev exec drush ev \$settings[trusted_host_patterns] [^my\-drupal\-site\.ddev\.site\$];重置。注意DDEV 的web容器日志默认级别是notice要看到warning和error需在.ddev/config.yaml中添加web_extra_exposed_ports: [] web_environment: - PHP_ERROR_REPORTINGE_ALL ~E_DEPRECATED ~E_USER_DEPRECATED5.3 模块启用失败drush en my_module报Class MyModule not found现象ddev exec drush en my_module -y后报错 Error: Class