Docker构建Node.js应用时npm install执行异常求助
环境信息
- Docker版本:
20.10.20 - npm版本:
8.5.2(必须使用--omit=dev而非--only=production) - Node.js版本:
16.14
问题历程
1. 初始构建错误
按照教程构建应用时,Dockerfile中RUN npm run install-client --omit=dev指令执行失败,错误信息:
executor failed running [/bin/sh -c npm install --prefix client --omit=dev]: exit code: 254
Dockerfile内容:
FROM node:16.14-alpine WORKDIR /app COPY package*.json ./ COPY client/package*.json client/ RUN npm run install-client --omit=dev COPY server/package*.json server/ RUN npm run install-server --omit=dev COPY client/ client/ RUN npm run build --prefix client COPY server/ server/ USER node CMD ["npm", "start", "--prefix", "server"] EXPOSE 8000
根目录package.json脚本配置:
"scripts": { "install-client": "npm install --prefix client", "install-server": "npm install --prefix server", "build": "npm run build --prefix client && npm start --prefix server", "docker-build": "docker build . -t alesssz/nasa-project" }
2. 修改基础镜像后的新问题
将FROM node:16.14-alpine改为FROM node:16-alpine后,初始错误消失,但RUN npm run install-client --omit=dev无限执行,添加--verbose查看日志,卡在安全审计步骤:
[ 5/10] RUN npm run install-client --omit=dev 59.7s => => # npm timing metavuln:cache:get:security-advisory:react-scripts:jzAvVcibtp6793goF6bMS+3REmxevJ33fk+CUpasW439H9DWo8HZryeL2vn3uGr5kT2MYZIC9lZQ2/rASfNe7w== Completed in 0ms => => # npm timing metavuln:load:security-advisory:react-scripts:6kGFeBaa+c/FiSh7gkidT8uneFtpq6JLmia0+ROmr6BVMW4bnUZ9bZd/dO+Squ13eCU8+LJ9HJjq2v7UKojEPA== Completed in 7ms => => # npm timing metavuln:cache:put:security-advisory:react-scripts:jzAvVcibtp6793goF6bMS+3REmxevJ33fk+CUpasW439H9DWo8HZryeL2vn3uGr5kT2MYZIC9lZQ2/rASfNe7w== Completed in 5ms => => # npm timing metavuln:calculate:security-advisory:react-scripts:6kGFeBaa+c/FiSh7gkidT8uneFtpq6JLmia0+ROmr6BVMW4bnUZ9bZd/dO+Squ13eCU8+LJ9HJjq2v7UKojEPA== Completed in 13ms => => # npm timing auditReport:init Completed in 19965ms => => # npm timing reify:audit Completed in 22816ms
3. 网络测试异常
在RUN npm run install-client --omit=dev前添加RUN ping registry.npmjs.org,发现该指令也无限执行(17分钟后手动终止),日志持续输出ping响应:
=> [ 6/12] RUN ping registry.npmjs.org => => # 64 bytes from 104.16.26.35: seq=1040 ttl=37 time=21.784 ms => => # 64 bytes from 104.16.26.35: seq=1041 ttl=37 time=25.782 ms => => # 64 bytes from 104.16.26.35: seq=1042 ttl=37 time=21.641 ms => => # 64 bytes from 104.16.26.35: seq=1043 ttl=37 time=24.249 ms => => # 64 bytes from 104.16.26.35: seq=1044 ttl=37 time=21.049 ms => => # 64 bytes from 104.16.26.35: seq=1045 ttl=37 time=19.880 ms
尝试docker run -it --rm node:16-alpine sh可以正常下载镜像并进入命令行,但构建时的问题仍未解决。
解决建议
1. 修复参数传递问题
npm run的参数需要通过--才能传递给脚本内部的命令,原指令中--omit=dev并没有传给install-client里的npm install,而是被当作npm run的参数,这是初始错误的核心原因。修改Dockerfile中的指令:
RUN npm run install-client -- --omit=dev RUN npm run install-server -- --omit=dev
2. 解决网络与无限执行问题
(1)修正网络测试命令
Alpine镜像的ping默认会无限发送数据包,测试网络应改为有限次数:
RUN ping -c 3 registry.npmjs.org
(2)切换npm镜像源
如果官方源网络不稳定,在Dockerfile中添加国内镜像源配置:
RUN npm config set registry https://registry.npmmirror.com/
将该指令放在RUN npm run install-client之前,加速依赖安装。
(3)跳过npm安全审计
从日志看构建卡在安全审计步骤,可在安装命令中添加--no-audit参数跳过:
- 方式一:修改根目录package.json的脚本:
"scripts": { "install-client": "npm install --prefix client --no-audit", "install-server": "npm install --prefix server --no-audit", // 其他脚本保留 }
- 方式二:在Dockerfile传递参数:
RUN npm run install-client -- --omit=dev --no-audit RUN npm run install-server -- --omit=dev --no-audit
(4)重置Docker网络
重启Docker Desktop,或者执行以下命令重置Docker网络:
docker network prune docker system prune -a
清理缓存后重新构建。
3. 优化Dockerfile(可选)
使用多阶段构建减少最终镜像体积,同时隔离构建环境与生产环境:
# 构建阶段 FROM node:16-alpine AS builder WORKDIR /app # 配置国内镜像源(可选) RUN npm config set registry https://registry.npmmirror.com/ COPY package*.json ./ COPY client/package*.json client/ COPY server/package*.json server/ RUN npm run install-client -- --omit=dev --no-audit RUN npm run install-server -- --omit=dev --no-audit COPY client/ client/ RUN npm run build --prefix client # 生产阶段 FROM node:16-alpine WORKDIR /app # 复制构建产物与依赖 COPY --from=builder /app/server/package*.json server/ COPY --from=builder /app/server/node_modules server/node_modules/ COPY --from=builder /app/client/build client/build/ COPY server/ server/ USER node CMD ["npm", "start", "--prefix", "server"] EXPOSE 8000
内容的提问来源于stack exchange,提问作者alesssz

