Skip to content

Docker Container Security Hardening: Distroless & Non-Root

CoreConceptAugust 1, 20263 min read

Containers are the foundation of modern cloud deployment, but default container images often ship with bloated Linux OS distributions containing package managers (apt, apk), shells (bash, sh), and outdated system utilities. If a vulnerability is exploited in your application, attackers can leverage these built-in utilities to escalate privileges or perform lateral network movement.

This guide covers essential container security hardening practices: Multi-Stage Builds, Google Distroless Base Images, Non-Root Execution, and Read-Only Root Filesystems.

Multi-Stage Builds & Distroless Base Images

Multi-Stage Builds separate the build-time SDK environment (which requires compilers, build tools, and package managers) from the runtime environment. The final production image copies only compiled application artifacts into a minimal runtime image.

Distroless images (maintained by Google) contain only your application and its runtime dependencies (Node.js, Python, Java, or Go binaries). They contain no package managers, shell interpreters, or standard Unix utilities, eliminating 90%+ of common CVE vulnerabilities.

Quick reference

  • Distroless images remove shell interpreters (sh, bash), preventing attackers from executing web shell payloads.
  • Executing as USER nonroot prevents container escape attacks from gaining root access on host Linux nodes.
  • Enforcing readOnlyRootFilesystem: true prevents malware from writing malicious scripts to the container disk.
Hardened Multi-Stage Dockerfile with Distroless
1# Stage 1: Build & Compile Application2FROM node:20-alpine AS builder3WORKDIR /app4COPY package*.json ./5RUN npm ci6COPY . .7RUN npm run build8 9# Stage 2: Production Distroless Runtime (No Shell / No Package Manager)10FROM gcr.io/distroless/nodejs20-debian12 AS runner11WORKDIR /app12ENV NODE_ENV=production13 14# Copy application artifacts from builder15COPY --from=builder /app/dist ./dist16COPY --from=builder /app/node_modules ./node_modules17 18# Run as non-root user (UID 65532 = nonroot in Distroless)19USER nonroot:nonroot20 21EXPOSE 300022CMD ["dist/index.js"]
Kubernetes SecurityContext Policy
1# Hardened Kubernetes Deployment Pod Security Context2apiVersion: apps/v13kind: Deployment4metadata:5  name: hardened-app6spec:7  template:8    spec:9      securityContext:10        runAsNonRoot: true11        runAsUser: 6553212        fsGroup: 6553213      containers:14        - name: app15          image: myrepo/hardened-app:latest16          securityContext:17            allowPrivilegeEscalation: false18            readOnlyRootFilesystem: true19            capabilities:20              drop:21                - ALL

Remember this

Using Distroless base images and non-root users eliminates the vast majority of container vulnerability attack vectors.

Container Vulnerability Scanning & Dropping Capabilities

Integrate automated container image vulnerability scanning (using tools like Trivy, Grype, or Docker Scout) into your CI/CD pipelines to catch vulnerable OS libraries before deployment.

Furthermore, drop all Linux Kernel Capabilities (capabilities.drop: ['ALL']) in your Kubernetes SecurityContext to enforce strict least-privilege container execution.

Quick reference

  • Run trivy image myrepo/app:latest in GitHub Actions to block builds containing Critical CVEs.
  • Mount ephemeral tmpfs volumes for temporary file processing when using read-only root filesystems.
  • Compare with Docker Multi-Stage Builds and Docker vs Kubernetes.

Remember this

Automated vulnerability scanning paired with dropped Linux capabilities creates a defensible container runtime posture.

Container Hardening Security Checklist

Follow this production checklist for hardening every container before shipping to Kubernetes or cloud servers.

For related guides, see our articles on CI/CD GitHub Actions Deployment and Kubernetes Request Flow.

Quick reference

  • Check 1: Minimal Base Image (Use Distroless or Alpine Linux).
  • Check 2: Non-Root Execution (USER nonroot:nonroot or USER 10001).
  • Check 3: Read-Only Root Filesystem (readOnlyRootFilesystem: true).
  • Check 4: Dropped Linux Capabilities (drop: ['ALL']).

Remember this

Adhering to minimal base images, non-root users, and read-only filesystems guarantees production container security.

Key takeaway

Hardening Docker containers with Distroless images, non-root users, and read-only filesystems turns containers into secure, unyielding production runtime environments.

Share:

Related Articles

Traditional perimeter-based security ('Castle and Moat') assumes that all traffic inside a private network or Kubernetes

Read

Docker and Kubernetes are not competitors on the same layer, and treating them as an either/or is the mistake that leads

Read

Containers are ephemeral by design — when you remove one, its filesystem disappears with it. That is fine for stateless

Read

Explore this topic

Keep learning

Follow a structured path or browse all courses to go deeper.