ddev中composer镜像易失效是因为容器每次重启都重建,composer config -g写入的全局配置不持久;唯一可靠方式是在项目composer.json的repositories数组首位声明镜像,且type必须为composer、url必须以/结尾。

为什么 ddev 中改 Composer 镜像容易失效
因为 ddev 默认以非 root 用户(如 ddev)运行容器,而 composer config -g 写入的是当前 shell 用户的 ~/.composer/config.json,但容器内实际执行命令的用户和宿主机用户不一致。更关键的是:ddev 的 PHP 容器每次启动都基于干净镜像重建,~/.composer/ 不持久化,全局配置一重启就丢失。
ddev 项目级镜像配置(推荐且唯一可靠方式)
必须在项目根目录的 composer.json 中声明 repositories,这是唯一能随容器生命周期稳定生效的方式:
- 把国内镜像放在
repositories数组第一位,例如阿里云:"repositories": [ { "type": "composer", "url": "https://mirrors.aliyun.com/composer/" }, { "type": "packagist", "url": "https://packagist.org" } ] - 确保
type是composer(不是packagist),否则 Composer 2.2+ 会报Invalid repository type "packagist" - URL 必须以
/结尾,https://mirrors.aliyun.com/composer/✅,https://mirrors.aliyun.com/composer❌ - 不要手动编辑
composer.json—— 用命令追加更安全:composer config repo.packagist composer https://mirrors.aliyun.com/composer/
ddev 启动时自动注入镜像配置(CI/自动化场景)
如果要用脚本或 CI 自动化初始化,可在 .ddev/docker-compose.override.yml 中挂载自定义配置,但更简单的是利用 ddev 的 hooks:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 在
.ddev/commands/host/composer-mirror(可执行)中写:#!/bin/sh ddev exec "composer config repo.packagist composer https://mirrors.aliyun.com/composer/"
- 然后执行:
ddev composer-mirror,它会进容器执行命令并写入项目级配置 - 注意:不能依赖
composer config -g,因为ddev exec默认以www-data用户运行,-g会写到/home/www-data/.composer/config.json,但该路径不持久
验证镜像是否真在用
别信 composer config --list 输出——它只显示配置,不反映实际请求。真正验证方法只有两个:
- 清缓存:
ddev exec "composer clear-cache",再跑ddev exec "composer require monolog/monolog --no-install -vvv 2>&1 | grep Downloading",看 URL 是否含mirrors.aliyun.com - 或者抓包:在容器里临时装
curl,执行ddev exec "curl -I https://mirrors.aliyun.com/composer/packages.json"确认域名可达;若返回 404,大概率是 URL 少了末尾/
最常被忽略的点:ddev 容器里 PHP CLI 和 Web 请求走的是同一套 Composer 配置,但一旦项目 composer.json 有 repositories 字段,全局配置就完全无效——这点和本地开发环境不同,必须按项目级硬编码。










