Image Size, Security and Best Practices
Harry
· 14 Sep 2026
· 4 views
Advertisement
Smaller images with multi-stage builds
Build tools (compilers, dev dependencies) do not belong in the final image. A multi-stage build compiles in one stage and copies only the finished artifact into a tiny runtime stage:
FROM node:20 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY package*.json ./
RUN npm install --production
CMD ["node", "dist/server.js"]
The final image contains only production dependencies and the built output – often a fraction of the size.
Keep the build context clean
Add a .dockerignore so junk and secrets never enter the image:
node_modules
.git
.env
*.log
Do not run as root
By default containers run as root, which is risky. Create and switch to an unprivileged user:
RUN addgroup -S app && adduser -S app -G app
USER app
Handle secrets and tags properly
- Never bake passwords or API keys into an image – pass them at run time via environment variables or secret managers.
- Avoid the
latesttag in production; pin explicit versions (myapp:1.4.2) so deployments are reproducible. - Prefer small, official base images (Alpine or
-slimvariants) to cut size and attack surface.
Key points
- Multi-stage builds keep build tools out of the final image, shrinking it dramatically.
- A
.dockerignorestops secrets and cruft from entering the build context. - Run as a non-root user and inject secrets at run time, never at build time.
- Pin explicit image tags for reproducible, auditable deployments.