Docker+Symfony环境下composer install命令未执行问题排查
问题排查与解决方案
核心原因分析
本地挂载覆盖容器内容
你的docker-compose.yml中php服务配置了volumes: - './:/var/www/html',这会将本地项目根目录直接挂载到容器内的/var/www/html目录。而Dockerfile里的composer install是在镜像构建阶段执行的,依赖会安装到容器内的/var/www/html/vendor,但启动容器时,本地目录(通常没有vendor)会覆盖容器内的这个目录,导致依赖消失,看起来像是composer install没运行。Docker构建缓存问题
如果你的composer.json和composer.lock没有修改,Docker会复用之前构建的镜像层,跳过composer install步骤,即使你修改了Dockerfile的其他部分(除非COPY的文件发生变化)。
解决方案
方案1:优化构建流程,避免挂载覆盖依赖
修改Dockerfile,将依赖安装与代码复制分离,同时通过挂载配置保留容器内的vendor目录:
1. 调整Dockerfile
ARG PHP_VERSION=8.1 FROM php:${PHP_VERSION}-fpm RUN apt-get update && apt-get install -y --no-install-recommends \ git \ zlib1g-dev \ libxml2-dev \ libzip-dev \ libpq-dev \ nano \ && docker-php-ext-install \ zip \ intl \ pdo \ mysqli \ pdo_mysql \ opcache # Install Composer RUN curl -sS https://getcomposer.org/installer | php && mv composer.phar /usr/local/bin/composer # Install Symfony CLI RUN curl -sS https://get.symfony.com/cli/installer | bash RUN mv /root/.symfony/bin/symfony /usr/local/bin/symfony # 先复制依赖文件,利用Docker缓存,仅当依赖文件变化时重新执行composer install COPY composer.json composer.lock* /var/www/html/ WORKDIR /var/www/html # 安装依赖,--no-scripts避免构建阶段执行Symfony需要数据库的脚本 RUN composer install --no-scripts --no-autoloader # 复制全部项目代码 COPY . /var/www/html/ # 生成自动加载文件并执行Symfony安装脚本 RUN composer dump-autoload --optimize && composer run-script post-install-cmd
2. 修改docker-compose.yml挂载配置
在php服务的volumes中添加匿名挂载,保留容器内的vendor目录不被本地覆盖:
php: container_name: ${APP_NAME}-php build: ./docker/php volumes: - './:/var/www/html' - /var/www/html/vendor # 匿名挂载,阻止本地目录覆盖容器内的依赖 environment: - APP_ENV=${APP_ENV} - APP_SECRET=${APP_SECRET} depends_on: - db networks: - myapp
同时在项目根目录创建.dockerignore文件,减少不必要的文件复制到镜像:
vendor/ .docker/ .env
方案2:容器启动时执行composer install(适合开发环境)
如果需要每次启动容器都安装依赖,可以在docker-compose.yml中添加启动命令:
php: container_name: ${APP_NAME}-php build: ./docker/php volumes: - './:/var/www/html' environment: - APP_ENV=${APP_ENV} - APP_SECRET=${APP_SECRET} command: sh -c "composer install && php-fpm" depends_on: - db networks: - myapp
注意:此方式每次启动容器都会执行composer install,生产环境不建议使用。
方案3:强制重新构建镜像(解决缓存问题)
如果是Docker构建缓存导致composer install未执行,执行以下命令强制重新构建:
docker-compose build --no-cache php docker-compose up -d
验证步骤
- 执行
docker-compose build --no-cache php,查看构建日志是否包含composer install的执行记录。 - 启动容器后,执行
docker-compose exec php ls /var/www/html/vendor,确认依赖目录存在。 - 若使用方案1,本地项目根目录不会生成vendor,但容器内的vendor正常可用。
内容的提问来源于stack exchange,提问作者Elell
相关产品推荐
相关产品推荐

