@@ -207,10 +207,20 @@ FROM node:alpine as app
207207COPY --from=builder node_modules .
208208```
209209
210-
211210## Smaller images without npm/yarn
212211
213- If you want to achieve an even smaller image size than the ` -alpine ` , you can omit the npm/yarn like this:
212+ To remove npm and Yarn package managers, use a multi-stage build.
213+ In the first stage, the package manager builds the app.
214+ In the second stage, the ` app ` and the ` node ` directories are copied,
215+ without copying the npm & Yarn package managers.
216+ In Docker images based on Node.js  ; >=26, Yarn is already removed.
217+
218+ The result is a smaller and hardened final image with no package managers.
219+ The size savings are typically about 2% or 3%.
220+
221+ The examples below build with npm.
222+
223+ ** Alpine example**
214224
215225``` Dockerfile
216226ARG ALPINE_VERSION=3.23
@@ -219,7 +229,7 @@ FROM node:24-alpine${ALPINE_VERSION} AS builder
219229WORKDIR /build-stage
220230COPY package*.json ./
221231RUN npm ci
222- # Copy the the files you need
232+ # Copy the files you need
223233COPY . ./
224234RUN npm run build
225235
@@ -240,3 +250,34 @@ COPY --from=builder /build-stage/dist ./dist
240250# Run with dumb-init to not start node with PID=1, since Node.js was not designed to run as PID 1
241251CMD ["dumb-init" , "node" , "dist/index.js" ]
242252```
253+
254+ ** Debian example**
255+
256+ ``` Dockerfile
257+ FROM node:24-trixie-slim AS builder
258+ WORKDIR /build-stage
259+ COPY package*.json ./
260+ RUN npm ci
261+ # Copy the files you need
262+ COPY . ./
263+ RUN npm run build
264+
265+ FROM debian:trixie-slim
266+ # Create app directory
267+ WORKDIR /usr/src/app
268+ # Add required binaries
269+ RUN apt-get update && apt-get install -y --no-install-recommends dumb-init \
270+ && rm -rf /var/lib/apt/lists/* \
271+ && groupadd --gid 1000 node \
272+ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node \
273+ && chown node:node ./
274+ COPY --from=builder /usr/local/bin/node /usr/local/bin/
275+ COPY --from=builder /usr/local/bin/docker-entrypoint.sh /usr/local/bin/
276+ ENTRYPOINT ["docker-entrypoint.sh" ]
277+ USER node
278+ # Update the following COPY lines based on your codebase
279+ COPY --from=builder /build-stage/node_modules ./node_modules
280+ COPY --from=builder /build-stage/dist ./dist
281+ # Run with dumb-init to not start node with PID=1, since Node.js was not designed to run as PID 1
282+ CMD ["dumb-init" , "node" , "dist/index.js" ]
283+ ```
0 commit comments