根本原因是默认构建将开发依赖、调试工具和完整PHP运行时全塞入生产镜像;应采用多阶段构建:第一阶段用php:7.4-cli安装Composer及依赖并清理.git/tests/docs;第二阶段基于php:7.4-alpine仅复制vendor/application/public等必要文件,禁用Xdebug、启用OPcache,并用.dockeringore排除冗余文件,最后用Dive分析镜像层定位大文件。
你的 ThinkPHP 5.1 项目 Docker 镜像体积突破 400MB,构建慢、拉取卡顿、CI 流水线频繁超时,根本原因不是框架本身臃肿,而是默认构建方式把开发期依赖、调试工具、完整 PHP 运行时全塞进了生产镜像。
第一步:在 Dockerfile 开头添加 builder 阶段,基于 php:7.4-cli(非 apache/fpm)安装 Composer 和依赖:
FROM php:7.4-cli AS builder
WORKDIR /app
COPY composer.json composer.lock ./
RUN apt-get update && apt-get install -y unzip git && rm -rf /var/lib/apt/lists/* &&
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer &&
composer install --no-dev --optimize-autoloader --no-progress
第二步:切换到精简运行阶段,使用 alpine 基础镜像并仅复制必要文件:
立即学习“PHP免费学习笔记(深入)”;
FROM php:7.4-alpine
WORKDIR /var/www/html
COPY --from=builder /app/vendor /var/www/html/vendor
COPY --from=builder /app/application /var/www/html/application
COPY --from=builder /app/extend /var/www/html/extend
COPY --from=builder /app/public /var/www/html/public
COPY --from=builder /app/think /var/www/html/think
COPY --from=builder /app/config /var/www/html/config
COPY --from=builder /app/runtime /var/www/html/runtime
COPY --from=builder /app/common.php /var/www/html/common.php
COPY --from=builder /app/index.php /var/www/html/public/index.php
EXPOSE 80
ENTRYPOINT ["php", "public/index.php"]
这一步必须严格区分路径——【runtime 目录不能直接 COPY,需在容器启动时初始化为空目录】,否则会继承 builder 阶段的缓存文件,导致权限错误或日志写入失败。
方法一:在 builder 阶段末尾加清理命令,防止 vendor 中混入 .git、tests、docs 等非运行必需内容:
RUN find /app/vendor -name ".git" -type d -exec rm -rf {} + 2>/dev/null || true &&
find /app/vendor -name "tests" -type d -exec rm -rf {} + 2>/dev/null || true &&
find /app/vendor -name "docs" -type d -exec rm -rf {} + 2>/dev/null || true
方法二:用 .dockerignore 排除源码中无用文件,避免它们被 COPY 进 builder 阶段:
.git
node_modules
tests
docs
README.md
.env.example
composer.phar
注意:【.dockerignore 必须放在构建上下文根目录,且文件名大小写必须为小写 .dockerignore】,写成 DOCKERIGNORE 或 .Dockerignore 都不会生效。
在 alpine 运行阶段的 Dockerfile 中追加 PHP 配置指令:
RUN docker-php-ext-enable opcache &&
{ echo 'opcache.enable=1';
echo 'opcache.memory_consumption=128';
echo 'opcache.interned_strings_buffer=8';
echo 'opcache.max_accelerated_files=4000';
echo 'opcache.revalidate_freq=60';
echo 'opcache.fast_shutdown=1'; } > /usr/local/etc/php/conf.d/opcache.ini
这一步操作起来很简单,直接把配置写进 ini 文件就行。但必须确认 Xdebug 没被意外启用——alpine 镜像默认不装 Xdebug,只要没手动 RUN pecl install xdebug 就安全;若已装,必须加 RUN rm -rf /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini 彻底清除。
① 安装 Dive(Ubuntu/Debian):
sudo apt-get install dive
② 构建并立即分析镜像:
dive build -t tp51-prod .
③ 启动后按 ↑↓ 键切换图层,在右侧面板观察文件树,重点关注 public/static、public/uploads、vendor/composer/archives 这三个路径下的文件大小。如果发现某层新增了超过 5MB 的 .zip 或 .tar.gz 文件,说明 composer install 未加 --no-dev 导致下载了测试包。
④ 按 c 键进入对比模式,输入原始镜像标签(如 tp51-dev),直观查看哪些文件被成功剔除。此时左下角显示的“Image Efficiency”若低于 60%,说明仍有冗余可挖。