根本原因在于容器DNS、网络策略、挂载方式或时间同步未对齐,而非Composer配置错误;需优先验证DNS、强制IPv4+指定可信DNS、切阿里镜像源、禁用packagist回源、正确挂载vendor与缓存、同步系统时间。

根本不是 Composer 配置错了,而是容器启动时 DNS、网络策略、挂载方式或时间同步没对齐——超时只是表象。
为什么 Docker 里 Composer 总卡在 downloading 或 cloning
容器内执行 composer install 卡住,90% 不是包本身问题,而是底层环境没准备好。常见现象包括:Resolving dependencies 阶段无响应(DNS 解析失败)、Downloading 阶段停在某个 URL(镜像源不可达)、Cloning into 'vendor/xxx' 后不动(Git SSH 超时或 HTTPS 被拦截)。
关键点:Docker 默认不继承宿主机的 DNS 设置;某些企业网或 CI 平台会屏蔽 GitHub API;挂载宿主机代码目录时,vendor 写入可能被 NTFS 或 macOS 文件系统桥接拖慢;WSL2 容器时间漂移也会导致证书校验失败。
- 先验证 DNS:进容器运行
nslookup mirrors.aliyun.com,若超时或返回空,说明 DNS 不通 - 别依赖
--network host:它在 CI 或多容器编排中不可靠,应显式指定 DNS - 检查是否误用了
--prefer-source:它强制走 Git 克隆,在容器里更容易因 SSH key 缺失或代理缺失卡死
必须加的三行 Dockerfile 配置
这三行解决 80% 的构建失败,且不依赖宿主机环境:
- 强制用 IPv4 + 指定可信 DNS:
RUN echo "nameserver 8.8.8.8" > /etc/resolv.conf - 全局切阿里镜像源:
RUN composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ - 禁用 packagist.org 回源(防止 fallback 拖慢):
RUN composer config -g repo.packagist false
注意:repo.packagist 是单数,不是 repos.packagist;URL 末尾必须带 /,否则拼出的路径非法;改完立刻执行 composer clear-cache,否则旧缓存仍生效。
挂载 vendor 和缓存的正确姿势
开发时用 docker run -v $(pwd):/app 挂载代码,但 vendor 目录不能跟着一起挂载——尤其在 macOS/Windows 上,跨系统 I/O 会让 composer install 变得极慢甚至卡死。
- 推荐用命名卷管理 vendor:
docker run -v $(pwd):/app -v composer-vendor:/app/vendor php:8.3-cli composer install - 复用 Composer 全局缓存:
-v ~/.composer/cache:/root/.composer/cache:delegated(Linux/macOS 宿主机路径) - Windows 用户注意:PowerShell 中
~不展开,要用完整路径如C:\Users\name\AppData\Roaming\Composer\Cache
如果构建阶段不需要 vendor 写入(比如只跑 composer install --no-scripts --no-autoloader),干脆不挂载 vendor,避免任何 I/O 干扰。
CI 环境里最容易忽略的两个坑
GitHub Actions、GitLab CI 这类环境启动快、NTP 同步滞后,常导致 signature verification failed 或 cURL error 60。
- 时间同步必须等稳了再跑 Composer:
sleep 2 && timedatectl timesync-status --wait(--wait会阻塞直到同步完成) - Docker 容器必须挂载时区:
volumes: - /etc/localtime:/etc/localtime:ro,否则date输出和证书有效期比对会失败 - 别信
COMPOSER_PROCESS_TIMEOUT=0:它治标不治本;真正该做的是提前换源 + 清缓存 + 避免post-install-cmd在构建阶段执行
复杂点在于:这些配置相互耦合——DNS 错了,换源也白换;时间偏了,哪怕下载成功,签名验证也会崩;挂载方式不对,timeout 调再高也卡在 I/O 层。动手前先 docker exec -it your-container sh 进去手动跑一遍 composer install -v,看卡在哪一步,比盲目调参高效得多。


















