How can I reduce the size of my nest.js Docker container built with a multi-stage Dockerfile?

I am currently using a multi-stage Dockerfile to build and run a Node.js application. The final container size is approximately 600 MB, and I would like to reduce it further. Here’s my current Dockerfile:

# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
Add 
RUN npm install --cache /npm-cache

# Runtime stage
FROM node:18-alpine AS runtime
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

I suspect there are optimizations I could make, such as reducing the size of the build artifacts or excluding unnecessary files. How can I reduce the container size while ensuring the app functions correctly?

Well what you’re showing here is a development image, Nest compiles itself into a JavaScript project
If you look in package.json, you can see the “build” script runs nest build

That should generate a lightweight dist folder used for production, which you can copy into the final image and serve

It’s a good start to use stages. As @deanayalon suggests, only copy the build or dist folder over. Also don’t copy the whole node_modules folder, but use npm ci to only install required libraries for runtime, not for build time (no devDependencies from package.json).

Then check how large your base image and your final image is (docker images), if those numbers make sense. My node:lts-alpine is about 155MB with SvelteKit app about 300MB.