为何nerdctl无法像Docker一样缓存RUN npm ci构建层?
问题:Nerdctl构建时
RUN npm ci层无法缓存,Docker本地构建正常 本地使用Docker命令构建镜像时,RUN npm ci层可以正常命中缓存,但在K8s的Jenkins代理中使用nerdctl构建时,该层始终重新执行,其他所有层(包括之前的apt-get相关RUN层、package.json和package-lock.json的COPY层)均能正常缓存。
本地Docker构建日志(相关部分)
[+] Building 1.8s (14/14) FINISHED docker:default => [internal] load build definition from Dockerfile 0.1s => => transferring dockerfile: 1.39kB 0.0s => [internal] load .dockerignore 0.1s => => transferring context: 112B 0.0s => [internal] load metadata for docker.io/library/node:18-bullseye-slim 1.0s => [1/9] FROM docker.io/library/node:18-bullseye-slim@sha256:a6b88857a85c692ded74bee86c9d42630c646f8a77267c0a281fb726ae54cdba 0.0s => [internal] load build context 0.1s => => transferring context: 295.92kB 0.0s => CACHED [2/9] RUN apt-get update && apt-get install -y locales openssl curl ca-certificates gpg make --no-install-recommends && localed 0.0s => CACHED [3/9] RUN curl -fsSL https://pgp.mongodb.com/server-4.4.asc | gpg -o /usr/share/keyrings/mongodb-server-4.4.gpg --dearmor & 0.0s => CACHED [4/9] RUN apt-get install ibgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb -y 0.0s => CACHED [5/9] WORKDIR /opt/app 0.0s => CACHED [6/9] COPY package.json . 0.0s => CACHED [7/9] COPY package-lock.json . 0.0s => CACHED [8/9] RUN npm ci 0.0s => [9/9] COPY . . 0.3s => exporting to image 0.1s => => exporting layers
Jenkins代理中Nerdctl构建日志(相关部分)
#7 [4/9] RUN apt-get install ibgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb -y #7 CACHED #8 [2/9] RUN apt-get update && apt-get install -y locales openssl curl ca-certificates gpg make --no-install-recommends && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 && rm -rf /var/lib/apt/lists/* #8 CACHED #9 [6/9] COPY package.json . #9 CACHED #10 [3/9] RUN curl -fsSL https://pgp.mongodb.com/server-4.4.asc | gpg -o /usr/share/keyrings/mongodb-server-4.4.gpg --dearmor && echo "deb [ signed-by=/usr/share/keyrings/mongodb-server-4.4.gpg ] http://repo.mongodb.org/apt/debian buster/mongodb-org/4.4 main" | tee /etc/apt/sources.list.d/mongodb-org-4.4.list && apt-get update && apt-get install -y mongodb-org-tools mongodb-org-shell #10 CACHED #11 [7/9] COPY package-lock.json . #11 CACHED #12 [8/9] RUN npm ci #12 21.07 #12 21.07 added 212 packages, and audited 213 packages in 21s #12 21.07 #12 21.07 41 packages are looking for funding #12 21.07 run `npm fund` for details #12 21.10 #12 21.10 6 vulnerabilities (5 moderate, 1 critical) #12 21.10 #12 21.10 To address issues that do not require attention, run: #12 21.10 npm audit fix #12 21.10 #12 21.10 To address all issues (including breaking changes), run: #12 21.10 npm audit fix --force #12 21.10 #12 21.10 Run `npm audit` for details. #12 21.10 npm notice #12 21.10 npm notice New patch version of npm available! 10.2.3 -> 10.2.5 #12 21.10 npm notice Changelog: <https://github.com/npm/cli/releases/tag/v10.2.5> #12 21.10 npm notice Run `npm install -g npm@10.2.5` to update! #12 21.10 npm notice #12 DONE 24.7s
使用的Dockerfile
FROM node:18-bullseye-slim ## Update system and install deps RUN apt-get update && apt-get install -y locales openssl curl ca-certificates gpg make --no-install-recommends \ && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 \ && rm -rf /var/lib/apt/lists/* ## Install Mongo shell RUN curl -fsSL https://pgp.mongodb.com/server-4.4.asc | \ gpg -o /usr/share/keyrings/mongodb-server-4.4.gpg \ --dearmor \ && echo "deb [ signed-by=/usr/share/keyrings/mongodb-server-4.4.gpg ] http://repo.mongodb.org/apt/debian buster/mongodb-org/4.4 main" | tee /etc/apt/sources.list.d/mongodb-org-4.4.list \ && apt-get update \ && apt-get install -y mongodb-org-tools mongodb-org-shell ## Cypress dependencies RUN apt-get install ibgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb -y ## Get e2e app set up WORKDIR /opt/app COPY package.json . COPY package-lock.json . RUN npm ci COPY . . ## Environment setup ## Redacted a few env variables here, but this is already past the RUN layer in question. ## Electron is finicky ENV ELECTRON_EXTRA_LAUNCH_ARGS='--disable-gpu' ENV TERM=linux ## Finally, execute the make all CMD ["npm", "run", "run:ci:short"]
可能的原因及解决办法
1. 缓存哈希计算机制差异
Docker和nerdctl对构建层的缓存哈希计算逻辑可能存在细微差别,尽管COPY层显示已缓存,但后续RUN层的校验条件可能更严格。
- 解决:将两个COPY指令合并为一条,减少分层并统一缓存触发条件:
COPY package*.json ./
2. 文件元数据被修改
Jenkins拉取代码时,可能会修改package.json或package-lock.json的权限、修改时间等元数据,即使文件内容未变,nerdctl也会因为元数据变化认为缓存无效。
- 解决:在Jenkins构建脚本中重置文件元数据,比如:
cd <项目目录> # 统一修改文件时间为固定值,避免元数据差异 touch -t 202001010000 package.json package-lock.json
3. Nerdctl版本或配置问题
旧版本的nerdctl可能存在缓存bug,或者Jenkins代理中的nerdctl被添加了禁用缓存的参数。
- 解决:
- 升级nerdctl到最新稳定版;
- 检查构建命令,确保没有使用
--no-cache参数; - 构建时显式指定复用缓存:
nerdctl build --cache-from=<你的镜像名>:<标签>。
4. npm版本不一致
本地和容器内的npm版本可能存在差异,导致npm ci的输出层哈希不同,无法命中缓存。
- 解决:在Dockerfile中固定npm版本:
RUN npm install -g npm@10.2.5 RUN npm ci
验证步骤
- 在Jenkins代理中对比本地和远程的文件哈希,确认内容一致:
sha256sum package.json package-lock.json - 使用
nerdctl build --progress=plain构建,查看详细的缓存校验日志,定位未命中缓存的具体原因。
内容的提问来源于stack exchange,提问作者Zlatko
相关产品推荐
相关产品推荐

