结论是所有 composer install 必须在构建阶段、用与生产一致的 PHP 环境完成,而非运行时容器中安装;否则必卡网络、丢缓存、权限错、autoload 失效,且镜像不可重现。

直接说结论:别在运行时容器里装依赖,所有 composer install 必须在构建阶段、用与生产一致的 PHP 环境完成。 否则必卡网络、丢缓存、权限错、autoload 失效,且镜像不可重现。
为什么 composer install 总卡在 “Resolving dependencies”?
不是 Composer 慢,是 Docker 构建过程默认不复用宿主机缓存,又直连 packagist.org —— 国内基本超时。错误常表现为:file could not be downloaded: failed to open stream: Connection timed out 或卡住 5 分钟以上。
- 必须显式设国内镜像源,推荐阿里云:
RUN COMPOSER_REPO_PACKAGIST=https://mirrors.aliyun.com/composer/ composer install - Alpine 镜像需提前装证书:
RUN apk add --no-cache ca-certificates,否则报SSL certificate problem - 别信宿主机的
~/.composer/cache或auth.json—— 构建过程完全隔离,这些一概不读
composer.json 和 composer.lock 的 COPY 顺序为什么致命?
顺序错了,composer install 就会自动降级为 composer update,结果不可控,且改写 composer.lock —— 这个文件受 Git 管控,容器里改了也提交不了,下次构建就丢。
- 正确顺序只有这一种:
COPY composer.json composer.lock ./→ 立刻RUN composer install ... - 千万别在
RUN composer install前COPY . .或COPY . /app—— 改一个空格,整个vendor层全失效,重下全部包 - 后续再复制其余代码:
COPY . .(注意不是覆盖式复制,避免冲掉已安装的vendor)
容器里执行 composer require 报 Permission denied 怎么办?
这不是 Composer 错误,是挂载卷 UID/GID 不匹配。Mac/Windows 宿主机挂载的文件默认属主是 root:root(uid=0),但 PHP 容器常用用户是 www-data(uid=33)或非 root 用户(如 uid=1001),根本写不进 vendor/ 或缓存目录。
- 启动时强制指定用户:
docker run -u $(id -u):$(id -g) -v $(pwd):/app -w /app php:8.2-cli composer require monolog/monolog - 若已有
root属主的vendor/,进容器后先修复:chown -R 1001:1001 vendor/(按实际 UID 调整) - 永远别在容器里跑
composer update—— 它会改composer.lock,而该文件必须由宿主机提交
基础镜像里没 composer 命令?
官方 PHP 镜像(如 php:8.3-cli-alpine)默认不带 Composer,command not found 是常态。
- 推荐安装方式:
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer - Alpine 需先装依赖:
RUN apk add --no-cache curl openssl - 验证是否生效:
docker run --rm php:8.3-cli composer --version—— 这步不通,后面全白搭 - 别用
apt-get install composer(Debian/Ubuntu 源版本太旧,不兼容 v2 lock 文件)
真正麻烦的从来不是命令会不会敲,而是构建层顺序、网络源、UID 映射、锁文件管控这四点混在一起——漏一个,vendor 就得重下,镜像就不可重现,上线就出 Class not found。


















