必须在dockerfile的run阶段显式配置镜像源,因宿主机config不透传且默认直连packagist.org易超时或403;正确命令为run composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/,需确保键名准确、type值明确、url以https开头并结尾带/。

docker build 里 RUN composer install 总卡住或失败
根本不是网络不稳定,而是默认连 packagist.org 在国内 DNS 和 CDN 路由下大概率超时、403 或卡在 Downloading。不配镜像源,composer install 就不是“慢”,是“几乎必挂”。
- 必须在
RUN阶段显式配置镜像,不能依赖宿主机的~/.composer/config.json—— Docker 构建过程根本不读它 - 正确写法:
RUN composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/(注意:repo.packagist是单数、小写;composer是 type 值,不能省;URL 必须以https://开头且末尾带/) - 验证是否生效:
RUN composer config -g repo.packagist输出应为完整 URL 或 JSON 对象;如果为空或仍是https://packagist.org,说明没写进去 - Alpine 镜像还需提前装证书:
RUN apk add --no-cache ca-certificates,否则报SSL certificate problem
Dockerfile 中 COPY 和 RUN 的顺序影响可重现性
composer.lock 是你依赖版本的唯一权威来源,但顺序一错,install 就会退化成 update,镜像就不可重现。
- 必须先
COPY composer.lock .,再COPY composer.json .,最后RUN composer install --no-dev --optimize-autoloader - 如果先
COPY . /app再RUN composer install,哪怕只改一行代码,Docker 缓存就失效,整个vendor/重装,构建极慢 - 别在
RUN composer install前启用--ignore-platform-reqs—— 这会掩盖 PHP 扩展缺失问题(比如缺mbstring或zip),导致运行时报错
多阶段构建中 vendor 复制容易漏掉 autoload 优化
最终镜像体积和启动性能,取决于 builder 阶段是否真正清理了 dev 依赖和未优化的 autoloader。
- builder 阶段用
php:8.3-cli(别用alpine,除非你确认所有扩展都装齐),RUN composer install --no-dev --optimize-autoloader - 复制时别只
COPY --from=builder /app/vendor /app/vendor,还要确保autoload.php已生成且路径一致 - 最终运行镜像里如果还残留
composer.json或composer.lock,说明没清理干净;它们不是运行必需,反而可能被误触发composer dump-autoload - 如果项目用了插件(如
phpstan或larastan),它们会被--no-dev过滤掉 —— 这是预期行为,别因此加回--dev
容器内执行 composer require 报 Permission denied
这不是 Composer 的 bug,是 UID/GID 不匹配导致的文件系统权限拒绝,尤其在 Mac/Windows 上挂载宿主机目录时高频出现。
- 宿主机挂载的
vendor/默认属主是root:root(uid=0),但 PHP 容器常用用户是www-data(uid=33)或非 root 用户(如 uid=1001) - 启动时强制指定用户:
docker run -u $(id -u):$(id -g) -v $(pwd):/app -w /app php:8.3-cli composer require monolog/monolog - 如果
vendor/已被 root 创建,进容器后先chown -R 1001:1001 vendor/(按实际 UID 调整) - 绝对不要在容器里跑
composer update—— 它会改composer.lock,而该文件受 Git 管控,改了也提交不了,下次构建就丢











