Skip to main content

Command Palette

Search for a command to run...

Hardened Docker Images: Building Secure Containers for Production

Containers have transformed how we build and deploy applications. But with great convenience comes great responsibility—security.

Updated
4 min read
Hardened Docker Images: Building Secure Containers for Production
S

As a seasoned system administrator with a passion for technology and problem-solving, I bring 6 Years of hands-on experience in managing and maintaining IT infrastructure. My journey in the field began with a deep curiosity for computers and systems, which has evolved into a fulfilling career dedicated to ensuring the smooth operation of critical business systems.

A standard Docker image often includes unnecessary packages, root access, and misconfigurations that can expose your application to risks. This is where hardened Docker images come in.

In this article, we’ll explore what hardened images are, why they matter, and how to build them effectively.


What Are Hardened Docker Images?

A hardened Docker image is a container image that has been:

  • Minimized to include only essential components

  • Configured with strict security practices

  • Scanned and patched for vulnerabilities

  • Designed to reduce attack surface

In simple terms: Same app, but with fewer ways to break into it.


Why You Should Care

Using default images from public registries can introduce risks:

  • Unnecessary tools (curl, bash, package managers)

  • Running containers as root

  • Outdated or vulnerable dependencies

  • Large attack surface

A compromised container can lead to:

  • Data breaches

  • Privilege escalation

  • Lateral movement inside your infrastructure


Key Principles of Hardening Docker Images

1. Use Minimal Base Images

Avoid bloated images like ubuntu unless required.

Better alternatives:

  • alpine

  • distroless

  • scratch

✔ Smaller size ✔ Fewer vulnerabilities


2. Run as Non-Root User

By default, containers run as root — this is dangerous.

RUN useradd -m appuser
USER appuser

Limits damage if compromised


3. Remove Unnecessary Packages

Install only what your app needs.

RUN apt-get update && apt-get install -y \
    nodejs \
 && rm -rf /var/lib/apt/lists/*

Reduces attack surface


4. Use Multi-Stage Builds

Separate build and runtime environments.

# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build

# Runtime stage
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist .
CMD ["node", "app.js"]

Keeps final image clean and lightweight


5. Scan Images for Vulnerabilities

Use tools like:

  • Trivy

  • Clair

  • Docker Scout

trivy image myapp:latest

Detects known CVEs


6. Avoid Hardcoding Secrets

Never store secrets in images.

Bad:

ENV DB_PASSWORD=secret123

✔ Use:

  • Environment variables

  • Secret managers (Vault, AWS Secrets Manager)


7. Set Proper File Permissions

Limit access inside the container:

RUN chmod 500 /app

Prevents unauthorized modifications


8. Use Read-Only Filesystem (Runtime)

Run containers with:

docker run --read-only myapp

Prevents file system tampering


9. Limit Container Capabilities

Drop unnecessary Linux capabilities:

docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp

Principle of least privilege


10. Keep Images Updated

Regularly rebuild images to patch vulnerabilities:

docker build --no-cache -t myapp:latest .

Ensures latest security updates


Example: Hardened Dockerfile

FROM node:18-alpine

# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR /app

COPY package*.json ./
RUN npm install --only=production

COPY . .

# Set ownership
RUN chown -R appuser:appgroup /app

USER appuser

EXPOSE 3000

CMD ["node", "app.js"]

Bonus: Distroless Images

Distroless images contain:

  • No shell

  • No package manager

  • Only runtime dependencies

✔ Extremely secure ✔ Very small footprint


Final Thoughts

Hardened Docker images are not optional anymore—they are essential.

If you're running containers in production:

  • Reduce attack surface

  • Follow least privilege

  • Continuously scan and update

Security is not a one-time step—it’s a continuous process.


What’s Next?

If you're managing infrastructure or Kubernetes clusters, the next step is:

  • Enforcing policies (OPA, Kyverno)

  • Using signed images

  • Implementing runtime security (Falco, etc.)


Have you hardened your Docker images yet? Let’s discuss your approach in the comments!

Container Security Deep Dive

Part 1 of 4

A practical series focused on securing Docker containers in real-world environments. Learn how to harden images, reduce attack surfaces, manage vulnerabilities, and follow DevSecOps best practices for production-ready systems.

Up next

Dockerfile Security Best Practices: A Complete Guide to Building Secure Docker Images

Docker Security Series – Part 2