5

I have a dockerfile where I am using alpine-nodejs version 16 as the base image. The npm version is 8.

When the step of npm install --production is executed while doing docker build, it is also installing dependencies listed under dev-dependencies of package.json, contrary to the use-case of production flag. I also used npm install --only=production but that also doesn't seem to work.

With alpine nodejs version 14, the flag is working as expected and dev-dependencies are not getting installed in container. Is there any issue with alpine node version 16 image? Thanks.

roadBurner
  • 63
  • 2
  • 8
  • What would be the expected behavior as opposed to what is actually happening? – Fred Feb 14 '22 at 18:09
  • Expectation is that it should not install dependencies mention within devdependencies block in package.json. Whereas currently it is installing both devdependencies as well as dependencies. – roadBurner Feb 14 '22 at 18:29
  • 2
    Can you edit the question to include a [mcve]? How do you tell the wrong dependency set is being installed? – David Maze Feb 14 '22 at 22:15
  • I can confirm the same problem `with node:16.14-stretch-slim` image. – Passiday Mar 18 '22 at 14:59
  • @Passiday - I have found the root cause of the issue after struggling on it for weeks. Kindly, look for my answer.Hope it helps. Thanks. – roadBurner Mar 19 '22 at 15:40

4 Answers4

3

I suspect your Dockerfile probably has something like COPY . . but you don't set .dockerignore correctly, e.g. you didn't add node_modules to your .dockerignore (check COPY with docker but with exclusion for the further information about .dockerignore)

I made the same mistake too and it should have nothing do with nodejs14 or nodejs16

BTW, npm install --only=prod[uction] is npm 6.x format and npm install --production is npm 8.x format. One difference is that in npm 8.x if you set NODE_ENV production npm 8.x will only install dependencies even if you run npm install but for npm6.x npm install --only will ignore NODE_ENV

Qiulang
  • 10,295
  • 11
  • 80
  • 129
1

After struggling with this for weeks, I have finally found the root cause and it is really dumb of me to not pay attention to that, I don't want others to make the same mistake. Since the code is proprietary, I can't share it. But I will explain the problem.

The image with nodejs:16 uses npm 8.0 whereas the one with nodejs:14 uses some npm version < 8.0.

The difference between them is in version 8.0, npm will also install the dependencies listed within peerDependencies block. (I am unsure if this behavior started from npm 8.0 or some previous versions)

So, why did I think npm is installing both devDependencies as well as dependencies?

When I was working with the nodejs:14 image, I moved certain dependencies from dependencies block to devDependencies block. So when I upgraded to nodejs:16, those dependencies returned.

Actually, the reason they came back because they were being internally used by a transitive dependency, which was listed within peerDependency block of package.json.

So, the takehome lesson?

Make sure the dependency you want to be removed isn't being consumed directly or transitively within dependency as well as peerDependency block.

Lee Goddard
  • 10,680
  • 4
  • 46
  • 63
roadBurner
  • 63
  • 2
  • 8
1

Starting from NPM 8, the flag to install only production dependencies changed. Instead of specifying which dependencies to install:

--only=production

We now specify which dependencies to omit:

--omit=dev

If we're using the latest version of NPM, we'll want to use this new approach each time we run npm install in our Dockerfile. For example, we want to use:

RUN npm run install-server --omit=dev

Rather than:

RUN npm run install-server --only=production
markmaksi
  • 11
  • 2
-1

It seems that npm ignores --production (or equivalent) flags when package-lock.json file is present.

Dragas
  • 1,140
  • 13
  • 29