必须在构建阶段执行composer install,因启动时运行会导致每次容器启动都重装依赖、缓存失效、网络失败风险高、扩展缺失无法修复,且违反“一次构建、多次运行”原则。

不能在容器启动时运行 composer install,必须在构建阶段完成。这是硬性约束,不是可选项。
为什么 composer install 必须放在 RUN 而非 CMD 或 ENTRYPOINT
常见错误是把安装逻辑塞进启动命令里,比如:CMD ["sh", "-c", "composer install --no-dev && php -S 0.0.0.0:8000"]。这会导致:
- 每次
docker run都重新拉包,网络不稳定就失败 -
vendor/不进镜像层,后续任何COPY或RUN都会让该步骤失效(缓存完全丢失) - 生产环境禁外网时,
Could not fetch packages直接导致容器退出 - PHP 扩展缺失(如
ext-zip)要到启动时才暴露,但此时镜像已无法修复
docker-php-ext-install 失败的 90% 原因:缺系统级开发包
docker-php-ext-install 只负责编译,不解决底层依赖。没装对应 -dev 包,必然失败。
- 装
zip扩展前,必须先RUN apt-get install -y libzip-dev - 装
pdo_mysql需default-libmysqlclient-dev(Debian/Ubuntu)或mysql-client mysql-devel(Alpine) - 装
gd需libfreetype6-dev libjpeg-dev libpng-dev - 装
sodium需libsodium-dev,再执行docker-php-ext-install sodium
Dockerfile 分层顺序决定构建成败
关键不是“能不能装上”,而是“哪一层装、装什么、怎么清理”。典型安全顺序:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
FROM php:8.1-cli-slim- 先装系统依赖:
RUN apt-get update && apt-get install -y libzip-dev default-libmysqlclient-dev && rm -rf /var/lib/apt/lists/* - 再装 PHP 扩展:
RUN docker-php-ext-install zip pdo_mysql - 最后装 Composer 依赖:
COPY composer.json composer.lock ./ && RUN composer install --no-dev --optimize-autoloader
注意:composer install 前必须 COPY 锁文件,否则无法复现依赖版本;--optimize-autoloader 对生产环境必不可少。
最容易被忽略的是锁文件与镜像层的绑定关系——composer.lock 改动后,只有紧随其后的 RUN composer install 层会重建,前面的扩展安装层不受影响。一旦把 composer install 拖到启动时,这个确定性就彻底消失。










