Class not found是因挂载vendor后UID/GID不匹配导致PHP进程无法读取autoload.php;应避免直接挂载vendor,改用命名卷+显式指定user,并在构建阶段修正属主权限。

vendor目录挂载后Class not found报错
这不是autoload没生成,而是挂载进来的vendor文件属主不匹配——宿主机UID=501(macOS)或1000(Linux),而容器内PHP进程默认以www-data(UID=33)或root运行,导致PHP读不到vendor/autoload.php里的类定义。
- 开发时别挂载整个
vendor目录;只挂载源码,比如./src:/app/src,然后在容器内跑composer install - 若必须挂载(如CI中复用缓存卷),提前在宿主机执行
chown -R 1001:1001 vendor(假设容器里PHP用户UID=1001) - 容器启动后手动执行一次
composer dump-autoload -o,避免因挂载文件系统缓存导致类路径未刷新
docker-compose.yml里怎么写vendor映射才安全
直接volumes: - ./vendor:/app/vendor是高危操作:不同系统UID/GID不一致、Windows换行符污染、MacFS元数据残留都会让autoload_classmap.php失效。
- 改用命名卷:
volumes: - vendor_cache:/app/vendor,并在services外定义volumes: vendor_cache: - 在
php服务里加user: "${UID:-1001}:${GID:-1001}",对齐宿主机身份 - 不要在
command里自动composer install——命名卷首次为空时会失败,应由开发者显式触发docker-compose run --rm php composer install
多阶段构建中vendor路径怎么复制才不丢权限
从构建阶段复制vendor到运行阶段时,如果用COPY --from=builder /app/vendor /app/vendor,默认属主是root,而运行阶段的PHP用户可能无权读取。
- 在构建阶段末尾加
RUN chown -R 1001:1001 /app/vendor(与运行阶段UID一致) - 运行阶段Dockerfile开头就创建对应用户:
USER 1001,而非依赖镜像默认的root - 避免用
ADD或COPY复制整个vendor——它包含大量小文件,Docker层打包慢;优先用COPY --from=builder精准复制
为什么config.platform.php会导致vendor路径解析异常
config.platform.php不是路径配置项,但它会强制Composer按声明的PHP版本解析composer.lock中的依赖约束。一旦声明的平台版本与容器实际PHP版本(php -v)或扩展(php -m)不一致,Composer就会跳过某些包的安装,导致vendor里缺类文件,autoload自然失败。
- 检查
composer.lock顶部platform字段是否显式锁定了PHP和扩展版本 - 容器内运行
php -v && php -m | grep -E "pdo|mbstring|json",确认实际环境与platform声明一致 - 构建前在宿主机跑
composer update --lock --no-dev,再提交更新后的composer.lock,比用--ignore-platform-reqs更可靠
真正卡住人的从来不是路径写法本身,而是挂载、复制、用户身份、平台声明这四层权限/版本耦合在一起时,任意一层错位都会让vendor变成“看得见摸不着”的黑洞。


















