最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

npm - Does it make a difference cleaning up on multi stage builds with Docker? - Stack Overflow

programmeradmin3浏览0评论

I've been learning about Docker and I had a Dockerfile like this one:

FROM node
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build && npm cache clean --force && rm -rf node_modules
CMD ['npm', 'start']

Then I learned about multi-stage build and changed the Dockerfile to this:

FROM node AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:lts-alpine
WORKDIR /app
COPY --from=builder /dist /app
CMD ['npm', 'start']

I imagined I could remove the npm cache clean --force && rm -rf node_modules since these artifacts wouldn't be present in the final image and the build would be a little bit faster. But then I read somewhere that those artifacts would still use some space, being present in the cache.

So I did a test:

  1. Run docker builder prune --all;
  2. I built with npm cache clean --force && rm -rf node_modules
  3. Run docker builder prune --all again. Total: 912.7MB
  4. I built without npm cache clean --force && rm -rf node_modules.
  5. Run docker builder prune --all again. Total: 912.7MB (just like before).

Running docker history <image> right after each build didn't show any difference either. So are the npm cache and node_modules really cached by docker and using some space somewhere and I'm missing something or can I get away with the faster Dockerfile not minding cleaning them up? Just keeping the cleaning would be a good practice?

I've been learning about Docker and I had a Dockerfile like this one:

FROM node
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build && npm cache clean --force && rm -rf node_modules
CMD ['npm', 'start']

Then I learned about multi-stage build and changed the Dockerfile to this:

FROM node AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:lts-alpine
WORKDIR /app
COPY --from=builder /dist /app
CMD ['npm', 'start']

I imagined I could remove the npm cache clean --force && rm -rf node_modules since these artifacts wouldn't be present in the final image and the build would be a little bit faster. But then I read somewhere that those artifacts would still use some space, being present in the cache.

So I did a test:

  1. Run docker builder prune --all;
  2. I built with npm cache clean --force && rm -rf node_modules
  3. Run docker builder prune --all again. Total: 912.7MB
  4. I built without npm cache clean --force && rm -rf node_modules.
  5. Run docker builder prune --all again. Total: 912.7MB (just like before).

Running docker history <image> right after each build didn't show any difference either. So are the npm cache and node_modules really cached by docker and using some space somewhere and I'm missing something or can I get away with the faster Dockerfile not minding cleaning them up? Just keeping the cleaning would be a good practice?

Share Improve this question edited 15 hours ago Noberto Pessoa asked 20 hours ago Noberto PessoaNoberto Pessoa 1253 silver badges12 bronze badges 2
  • docker history shows the layers in the final image. Not the cache. And as you've seen, cleaning the cache doesn't affect the final image. It's probably correct that the cache is bigger if you don't clean it up, but it's not something I'd worry about. – Hans Kilian Commented 19 hours ago
  • Thanks for clarifying about docker history! But what about docker builder prune -a freeing the exact same space? Does that mean the cache didn't change or maybe I'm mistaken about something else? – Noberto Pessoa Commented 19 hours ago
Add a comment  | 

1 Answer 1

Reset to default 0

The particular Dockerfile setup you show makes no difference in terms of space. A multi-stage Dockerfile helps when

  1. You need some set of libraries only to build the application, but not to run it; and
  2. In the final build stage you only copy or install the specific things you need into the image.

Since you're copying the entire /app directory in, the final image is basically the same as the build stage. You're right that RUN rm ... does not decrease the image size; but conversely, you can't discard the node_modules directory either, because that contains the libraries your application needs to run.

Let's say, hypothetically, that you have a Typescript-based application. Your package.json file lists tsc in the devDependencies section: you need to compile Typescript to plain Javascript, but having done that, you do not actually need the Typescript compiler any more. Here you could usefully have two stages

  1. Install tsc and all of the devDependencies, and compile the application; then
  2. Install only the dependencies but not the devDependencies, plus the compiled application but not the original .ts files.

That Dockerfile might look like

FROM node:lts AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY ./ ./
RUN npm run build

FROM node:lts
WORKDIR /app
COPY package.json package-lock.json ./
ENV NODE_ENV=production
RUN npm ci
COPY --from=build /app/dist/ /app/dist/
CMD ["node", "dist/index.js"]

Since the second stage sets NODE_ENV=production, the npm ci step omits the devDependencies, and you'll get a smaller final image.

发布评论

评论列表(0)

  1. 暂无评论