Docker构建时执行npm install未生成node_modules文件夹问题咨询
问题原因与解决方案
根因定位
你遇到的产物消失问题完全是Dockerfile指令顺序错误导致的,和「在容器内执行编译」的操作本身无关:
- 你先通过
COPY ./www /var/www将本地无node_modules、无编译产物的代码复制到容器工作目录 - 后续执行的
RUN npm install、RUN npm run production确实成功生成了node_modules文件夹和编译产物 - 但你在编译指令后又连续执行了两次
COPY ./www /var/www,直接用本地的原始代码覆盖了容器内已经生成好编译结果的目录,之前生成的所有内容都被清空替换,自然看不到产物。
另外你的Dockerfile还有两处冗余/错误配置:
- 末尾的
ENTRYPOINT ["npm", "run"]会覆盖默认的CMD ["php-fpm"]启动逻辑,导致容器启动后不会运行php-fpm服务,完全不符合你的镜像设计目标 - 重复的COPY操作也会无端增大镜像体积,拉长构建时间
修正方案
按以下顺序调整Dockerfile即可:
FROM php:8.0-fpm # Copy composer.lock and composer.json #COPY composer.lock composer.json /var/www/ # Set working directory WORKDIR /var/www # Install dependencies RUN apt-get update && apt-get install -y libonig-dev libpq-dev \ build-essential \ libpng-dev \ libjpeg62-turbo-dev \ libfreetype6-dev \ locales \ zip \ jpegoptim optipng pngquant gifsicle \ vim \ unzip \ git \ curl \ libzip-dev RUN apt-get -y install nodejs RUN apt-get -y install npm # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Install extensions RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl RUN docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/ RUN docker-php-ext-install gd # Install composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Add user for laravel application RUN groupadd -g 1000 www RUN useradd -u 1000 -ms /bin/bash -g www www # Copy existing application directory contents COPY ./www /var/www ARG CACHE_DATE=not_a_date RUN npm install RUN npm run production # 直接给已有文件赋权,不要重复COPY本地代码 RUN chown -R www:www /var/www # Change current user to www USER www # Expose port 9000 and start php-fpm server EXPOSE 9000 CMD ["php-fpm"]
关于容器内编译的疑问解答
- 完全可以在Docker容器构建阶段执行npm类的编译命令,这是业内非常普遍的实现方案,本身没有任何问题。
- 这种做法反而能保证构建环境的一致性,不会因为本地开发环境的node版本、依赖配置差异导致编译结果不一致,也不需要开发者在本地提前安装编译相关的依赖工具。如果对镜像体积有要求,还可以进一步用多阶段构建的方式,把编译阶段和运行时阶段拆分,最终运行镜像只保留必要的运行依赖和编译产物,进一步减小镜像体积。
内容的提问来源于stack exchange,提问作者Troodi
相关产品推荐
相关产品推荐

