CloudOpsGuide
docker

Dockerfile Best Practices: Building Small, Secure Images

Beginner
9 minutes
October 2026
CloudOpsGuide Team

Dockerfile Best Practices: Building Small, Secure Images

A Dockerfile that works on your laptop and a Dockerfile that belongs in production are two different things. Here are the practices that separate them.

Table of Contents

1. Use multi-stage builds

Build dependencies (compilers, dev headers, test tooling) have no business in your final image. Multi-stage builds keep the runtime image small:

FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
USER node
CMD ["node", "dist/server.js"]

2. Pin your base images

FROM node:latest is a lottery. Pin to a specific version — better yet, a digest — so builds are reproducible and you upgrade deliberately.

3. Order layers for cache

Docker caches each layer. Copy package.json before the rest of the source so dependency installs are cached unless dependencies actually change:

COPY package*.json ./   # changes rarely
RUN npm ci              # cached layer
COPY . .                # changes often — cache busts here only

4. Don't run as root

Containers running as root give attackers a head start on container escapes. Most official images ship a non-root user — use it: USER node, or create your own.

5. Write a real .dockerignore

Without it, COPY . . ships your .git, node_modules, local .env files, and secrets into the image:

.git
node_modules
.env
*.md
.dockerignore

6. One process per container

Your container's PID 1 should be the app — not a shell script wrapping three daemons. Use CMD ["node", "server.js"] (exec form) so signals like SIGTERM reach the process and graceful shutdown works.

7. Scan before you ship

Run docker scout cves or trivy image myapp:latest in CI. Base images accumulate CVEs; catching them in the pipeline beats catching them in an incident.

Small images, non-root users, pinned versions, clean layers — apply these and your containers stop being a liability.

Related Articles


Last Updated: October 2026 Author: CloudOpsGuide Team Difficulty: Beginner Estimated Reading Time: 9 minutes