Why does `package-lock.json` causes a failure in a docker container build when `npm install`?

From your question:

Note: npm install works fine on my local machine, just fails in docker container

If you are using npm install, you are not sure to have the same version of dependencies.

For having a reproducible environment, without unexpected issues because of different version of dependencies, you’d rather use npm ci (clean-install):

This command is similar to npm-install, except it’s meant to be used
in automated environments such as test platforms, continuous
integration, and deployment – or any situation where you want to make
sure you’re doing a clean install of your dependencies. It can be
significantly faster than a regular npm install by skipping certain
user-oriented features. It is also more strict than a regular install,
which can help catch errors or inconsistencies caused by the
incrementally-installed local environments of most npm users.

In short, the main differences between using npm install and npm ci
are:

  • The project must have an existing package-lock.json or
    npm-shrinkwrap.json.
  • If dependencies in the package lock do not match those in package.json, npm ci will exit with an error, instead of updating the package lock.
  • npm ci can only install entire projects at a time: individual dependencies cannot be added with this command.
  • If a node_modules is already present, it will be automatically removed before npm ci begins its install.
  • It will never write to package.json or any of the package-locks: installs are essentially frozen.

A Fabian Gander’s article gives further clarification about the npm install and npm ci tools and provides advice on when to use each one. The below table is from that source:

  cases                                | npm install | npm ci
 --------------------------------------|-------------|-------------
  needs package.json                   | no          | yes
  needs package-lock.json              | no          | yes
  installs from package.json           | yes         | no
  installs from package-lock.json      | no          | yes
  compares both                        | no          | yes
  updates loose package versions       | yes         | no
  updates loose dependencies           | yes         | no
  writes to package.json               | yes         | no
  writes to package-lock.json          | yes         | no
  deletes node_modules before install  | no          | yes
  used for installing separate package | yes         | no
  should be used on build systems / CI | no          | yes
  can be used for development          | yes         | yes
  reproducible installs                | no          | yes

This is why package-lock.json is there, to be available for tools like npm ci.

After having a reproducible environment, if this doesn’t fix your issue, you need to keep investigating, but IMO it should be the first step.

Leave a Comment