node.js – Bumping package.json版本而不会使docker缓存失效

我正在使用一个非常标准的Dockerfile来容纳Node.js应用程序:

# Simplified version
FROM node:alpine

# Copy package.json first for docker build's layer caching
COPY package.json package-lock.json foo/
RUN npm install

COPY src/ foo/
RUN npm run build

将我的COPY分成两部分是有利的,因为它允许Docker缓存(长)npm安装步骤.

然而,最近,我开始使用semver来破坏我的package.json版本.这具有使npm安装步骤使Docker缓存无效的副作用,显着延长了我的构建时间.

是否有我可以使用的替代缓存策略,以便npm安装仅在我的依赖项更改时运行?

最佳答案
我花了一些时间思考这个问题.从根本上说,我是在作弊,因为事实上,package.json文件已被更改,这意味着任何绕过缓存失效的技术都会使构建无法重现.

但是,出于我的目的,我更关心构建时间而不是严格的缓存正确性.这是我想出的:

集结artifacts.js

/*
Used to keep docker cache fresh despite package.json version bumps.

In this script
- copy package.json to package-artifact.json
- zero package.json version

In Docker
- copy package.json
- run npm install normal
- copy package-artifact.json to package.json (undo-build-artifacts.js accomplishes this with a conditional check that package-artifact exists)
*/

const fs = require('fs');
const package = fs.readFileSync('package.json', 'utf8');
fs.writeFileSync('package-artifact.json', package);
const modifiedPackage = { ...JSON.parse(package), version: '0.0.0' };
fs.writeFileSync('package.json', JSON.stringify(modifiedPackage));

const packageLock = fs.readFileSync('package-lock.json', 'utf8');
fs.writeFileSync('package-lock-artifact.json', packageLock);
const modifiedPackageLock = { ...JSON.parse(packageLock), version: '0.0.0' };
fs.writeFileSync('package-lock.json', JSON.stringify(modifiedPackageLock));

撤消 – 建造 – artifacts.js

const fs = require('fs');

const hasBuildArtifacts = fs.existsSync('package-artifact.json');
if (hasBuildArtifacts) {
  const package = fs.readFileSync('package-artifact.json', 'utf8');
  const packageLock = fs.readFileSync('package-lock-artifact.json', 'utf8');

  fs.writeFileSync('package.json', package);
  fs.writeFileSync('package-lock.json', packageLock);

  fs.unlinkSync('package-artifact.json');
  fs.unlinkSync('package-lock-artifact.json');
}

这两个文件用于重定位package.json和package-lock.json,将其替换为具有清零版本的工件.这些工件将在docker构建中使用,并将在npm安装完成时替换为原始版本.

我在Travis CI before_script中运行build-artifacts.js,在Dockerfile本身中运行undo-build-artifacts.js(在我安装之后). undo-build-artifacts.js包含对构建工件的检查,这意味着如果build-artifacts.js尚未运行,Docker容器仍然可以构建.这使得容器在我的书中足够便携. 🙂

转载注明原文:node.js – Bumping package.json版本而不会使docker缓存失效 - 代码日志