Skip to content
DevOps, Linux & Docker

Docker Security Hardening in 2026: Non-Root, Distroless and Least Privilege

A comprehensive production security checklist for containerizing modern backend applications: unprivileged users, multi-stage builds, CVE scanning, and minimal base images.

Remix into Workplace Studio:

Why Default Dockerfiles Fail Security Audits

Most tutorials teach developers to write Dockerfiles that look like this:

FROM node:latest
WORKDIR /app
COPY . .
RUN npm install
CMD ["npm", "start"]

While functional for quick local testing, deploying this container to a production Kubernetes cluster or Linux VPS creates significant security vulnerabilities:

  1. Root Execution: By default, processes inside the container run as UID 0 (root). If an attacker exploits an unpatched library vulnerability (e.g. arbitrary code execution), they inherit root privileges inside the container namespace and can attempt container escape attacks.
  2. Floating Tags: Using :latest means deployments are non-deterministic. A new upstream release can break your build or introduce zero-day CVEs overnight.
  3. Bloated Attack Surface: Full Ubuntu or Debian images ship with package managers, compilers, and shells (curl, wget, bash) that attackers leverage for post-exploitation pivots.

1. The Hardening Checklist

Rule 1: Always Enforce an Unprivileged User

Create a dedicated system user and switch to it using the USER directive:

# Alpine example
RUN addgroup -S -g 10001 appgroup && \
    adduser -S -u 10001 -G appgroup appuser
USER appuser:appgroup

Rule 2: Multi-Stage Distroless or Alpine Builds

Separate the build dependencies from the final runtime container. Tools like compilers, Git, and package caches should never exist in the production image:

# Stage 1: Build
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev

# Stage 2: Runtime
FROM gcr.io/distroless/nodejs22-debian12:nonroot
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --chown=nonroot:nonroot . .
USER nonroot
EXPOSE 3000
CMD ["server.js"]

Rule 3: Add Native Healthchecks

Orchestrators need an internal signal to verify that your process has not entered an unrecoverable deadlock:

HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
  CMD ["node", "-e", "fetch('http://localhost:3000/health').then(r => r.ok ? process.exit(0) : process.exit(1))"]

2. Automated In-Browser AST Security Scanner

To verify your existing Dockerfiles against these benchmarks, use the Dockerfile AST Security Scanner on THE SABBiR OS.

It analyzes your directives, highlights security risks, scores your setup from 0 to 100, and provides a one-click generated production-hardened Dockerfile with clean multi-stage layering.

DockerDevOpsSecurityLinuxContainers
Md Sabbirul Islam Khan

Md Sabbirul Islam Khan

Written by THE SABBiR