Use smaller images

Always use smaller images such as alpine or slim rather than the usual base images.

Base image size: 1.0GB++

Alpine image size: ±250MB

FROM node:22-alpine

Or better, use distroless as it is not an OS and only a runtime environment for your application.

Distroless Github Link:

https://github.com/GoogleContainerTools/distroless

Do a proper layer caching

Put the most frequent changes on the end of the Dockerfile.

FROM node:22-alpine

WORKDIR /app

# Dependencies tends to change less than your code
# So it is executed first
COPY ./package*.json ./
RUN npm install

# Then you can copy your code
COPY . .
RUN npm run build
EXPOSE 4173
CMD ["npm", "run", "preview"]

Layer Squashing

Remove unnecessary context on your Dockerfile by utilizing .dockerignore on your project. Put it on the directory where your Dockerfile belongs.

# .dockerignore

# Node
node_modules                 # node_modules aren't necessary as you will build your app
npm-debug.log                # which compile them as static files
dist

# Version Control
.git
.gitignore

# IDE and Editor files
.vscode
.idea
*.swp
*.swo

# GOOD TO HAVE AS YOUR ENV ISN'T SUPPOSE TO BE ON YOUR DOCKER IMAGE
# Environment files
.env
.env.local
.env.*

# Testing
coverage
*.test.js

# DS Files
.DB_Store

Then to further your image size, you can clean up your project such as: