@@ -207,10 +207,19 @@ 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+
220+ The examples below build with npm.
221+
222+ ** Alpine example**
214223
215224``` Dockerfile
216225ARG ALPINE_VERSION=3.23
@@ -219,7 +228,7 @@ FROM node:24-alpine${ALPINE_VERSION} AS builder
219228WORKDIR /build-stage
220229COPY package*.json ./
221230RUN npm ci
222- # Copy the the files you need
231+ # Copy the files you need
223232COPY . ./
224233RUN npm run build
225234
@@ -240,3 +249,34 @@ COPY --from=builder /build-stage/dist ./dist
240249# Run with dumb-init to not start node with PID=1, since Node.js was not designed to run as PID 1
241250CMD ["dumb-init" , "node" , "dist/index.js" ]
242251```
252+
253+ ** Debian example**
254+
255+ ``` Dockerfile
256+ FROM node:24-trixie-slim AS builder
257+ WORKDIR /build-stage
258+ COPY package*.json ./
259+ RUN npm ci
260+ # Copy the files you need
261+ COPY . ./
262+ RUN npm run build
263+
264+ FROM debian:trixie-slim
265+ # Create app directory
266+ WORKDIR /usr/src/app
267+ # Add required binaries
268+ RUN apt-get update && apt-get install -y --no-install-recommends dumb-init \
269+ && rm -rf /var/lib/apt/lists/* \
270+ && groupadd --gid 1000 node \
271+ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node \
272+ && chown node:node ./
273+ COPY --from=builder /usr/local/bin/node /usr/local/bin/
274+ COPY --from=builder /usr/local/bin/docker-entrypoint.sh /usr/local/bin/
275+ ENTRYPOINT ["docker-entrypoint.sh" ]
276+ USER node
277+ # Update the following COPY lines based on your codebase
278+ COPY --from=builder /build-stage/node_modules ./node_modules
279+ COPY --from=builder /build-stage/dist ./dist
280+ # Run with dumb-init to not start node with PID=1, since Node.js was not designed to run as PID 1
281+ CMD ["dumb-init" , "node" , "dist/index.js" ]
282+ ```
0 commit comments