DEV Community

Thesius Code
Thesius Code

Posted on • Originally published at datanest-stores.pages.dev

Container Security Toolkit: Container Security Guide

Container Security Guide

A comprehensive approach to securing containers from build to runtime.

Datanest Digital — datanest.dev


Table of Contents

  1. Image Hardening
  2. Vulnerability Scanning Pipeline
  3. Policy Enforcement
  4. Runtime Security
  5. CI/CD Integration
  6. Compliance Mapping
  7. Incident Response

Image Hardening

Principle: Minimal, Immutable, Non-Root

Every container image should follow three principles:

  1. Minimal: Include only what the application needs to run. No shells, no package managers, no debugging tools in production images.
  2. Immutable: Never patch running containers. Rebuild and redeploy.
  3. Non-root: Never run as UID 0.

Multi-Stage Builds

Multi-stage builds are the foundation of hardened images. Build tools, compilers, and development dependencies never reach the final image:

# Build stage — has gcc, make, pip, etc.
FROM python:3.12-slim AS builder
COPY requirements.txt .
RUN pip install --prefix=/install -r requirements.txt

# Production stage — only runtime dependencies
FROM python:3.12-slim
COPY --from=builder /install /usr/local
COPY --chown=10001:10001 src/ ./src/
USER 10001
Enter fullscreen mode Exit fullscreen mode

Base Image Selection

Language Recommended Base Size Notes
Python python:X.Y-slim ~150MB Debian slim, includes glibc
Node.js node:X-alpine ~50MB Musl libc, smallest option
Go scratch or gcr.io/distroless/static ~2-10MB No OS at all
Java eclipse-temurin:X-jre + debian:slim ~100MB JRE only, no JDK

Checklist

  • [ ] Pin base image version (never use :latest)
  • [ ] Use multi-stage build
  • [ ] Run as non-root user with explicit UID
  • [ ] Set HEALTHCHECK instruction
  • [ ] Use COPY instead of ADD
  • [ ] No secrets in ENV or ARG
  • [ ] Add OCI labels for traceability
  • [ ] Use .dockerignore to exclude .git, node_modules, etc.

Vulnerability Scanning Pipeline

Defense in Depth: Multiple Scanners

No single scanner catches everything. Use at least two:

Scanner Strength Weakness
Trivy Fast, comprehensive, misconfigs Fewer language-specific advisories
Grype Strong language ecosystem coverage No misconfig scanning
Hadolint Dockerfile best practices Only lints Dockerfiles

Scanning Strategy

Developer Workstation     CI/CD Pipeline          Registry
       │                       │                      │
  hadolint lint           trivy image scan       periodic rescan
  (pre-commit)            grype image scan       (new CVE DB)
       │                  conftest policy         │
       │                       │                  │
       └──── Push ──── Build ── Scan ── Push ── Monitor
Enter fullscreen mode Exit fullscreen mode

Handling Findings

  1. CRITICAL: Block deployment. Fix immediately.
  2. HIGH: Block deployment. Fix within 7 days.
  3. MEDIUM: Allow deployment. Fix within 30 days.
  4. LOW: Track in backlog.

False Positives

Create a .trivyignore file for accepted risks:

# CVE-2024-12345: Not exploitable in our configuration
# Reviewed by: security-team, Date: 2026-01-15
CVE-2024-12345
Enter fullscreen mode Exit fullscreen mode

Always document the justification and review date.


Policy Enforcement

OPA (Open Policy Agent)

OPA policies enforce rules at build time using conftest:

# Test Dockerfiles against policies
conftest test Dockerfile -p policies/opa/

# Test Kubernetes manifests
conftest test deployment.yaml -p policies/opa/
Enter fullscreen mode Exit fullscreen mode

Key policies included:

  • dockerfile-policy.rego: No root, no latest, no ADD, no secrets in ENV
  • k8s-pod-security.rego: Restricted PSS profile enforcement

Kyverno

Kyverno policies enforce rules at deploy time as a Kubernetes admission controller:

# Install Kyverno
helm install kyverno kyverno/kyverno -n kyverno --create-namespace

# Apply policies
kubectl apply -f policies/kyverno/
Enter fullscreen mode Exit fullscreen mode

Key policies:

  • require-non-root: Containers must run as non-root
  • require-resource-limits: CPU/memory limits mandatory
  • require-image-digest: Images must use @sha256: references

Policy Modes

Mode Behavior Use Case
Enforce Block non-compliant resources Production
Audit Log violations but allow Migration period

Start in Audit mode, monitor violations, then switch to Enforce.


Runtime Security

Seccomp Profiles

Seccomp restricts which syscalls a container can make. The included profile blocks:

  • ptrace — Prevents debugging/container escape
  • mount/umount — Prevents filesystem manipulation
  • unshare/setns — Prevents namespace escape
  • kexec_load — Prevents kernel replacement
  • init_module — Prevents kernel module loading

Apply in Kubernetes:

securityContext:
  seccompProfile:
    type: Localhost
    localhostProfile: profiles/seccomp-profile.json
Enter fullscreen mode Exit fullscreen mode

AppArmor Profiles

AppArmor provides mandatory access control. The included profile:

  • Denies raw network sockets
  • Denies mount operations
  • Restricts file system access
  • Blocks execution from /tmp (common attack vector)
  • Denies ptrace
# Load profile on each node
sudo apparmor_parser -r /etc/apparmor.d/container-restricted

# Apply to pod
metadata:
  annotations:
    container.apparmor.security.beta.kubernetes.io/myapp: localhost/container-restricted
Enter fullscreen mode Exit fullscreen mode

Security Context Best Practices

Every production pod should have:

securityContext:
  runAsNonRoot: true
  runAsUser: 10001
  runAsGroup: 10001
  fsGroup: 10001
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  seccompProfile:
    type: RuntimeDefault
  capabilities:
    drop: ["ALL"]
Enter fullscreen mode Exit fullscreen mode

CI/CD Integration

GitHub Actions Pipeline

The included workflow (container-security.yml) implements:

  1. Lint — Hadolint checks Dockerfile best practices
  2. Build — Docker Buildx with layer caching and SBOM generation
  3. Scan — Trivy + Grype vulnerability scanning with SARIF upload
  4. Policy — conftest OPA policy validation
  5. Gate — Security summary with pass/fail gate

Pre-commit Hooks

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/hadolint/hadolint
    rev: v2.12.0
    hooks:
      - id: hadolint-docker
Enter fullscreen mode Exit fullscreen mode

Scheduled Rescanning

New CVEs are published daily. Rescan deployed images on a schedule:

on:
  schedule:
    - cron: '0 6 * * *'  # Daily at 6 AM UTC
Enter fullscreen mode Exit fullscreen mode

Compliance Mapping

Security Control CIS Docker 1.6 CIS Kubernetes 1.8 NIST 800-190
Non-root user 4.1 5.2.6 CM-7
Read-only rootfs 5.12 5.2.4 AC-6
Resource limits 5.10 5.2.7 SC-6
Image scanning 4.4 RA-5
Seccomp profiles 5.2 5.2.2 SC-39
No privileged 5.4 5.2.1 AC-6(1)
Image signing 4.5 SI-7
Network policies 5.3.2 SC-7

Incident Response

Container Compromise Playbook

  1. Isolate: Apply a deny-all NetworkPolicy to the compromised pod
  2. Capture: Export container filesystem for forensics
   kubectl cp <pod>:/app ./forensics/app-snapshot
   docker export <container> > forensics/container.tar
Enter fullscreen mode Exit fullscreen mode
  1. Investigate: Check logs, network connections, process list
  2. Remediate: Rebuild from clean base image, rotate secrets
  3. Harden: Add policies to prevent recurrence

Useful Forensics Commands

# Check running processes in container
kubectl exec <pod> -- ps aux

# Check network connections
kubectl exec <pod> -- netstat -tlnp

# Check for unexpected SUID binaries
kubectl exec <pod> -- find / -perm -4000 -type f 2>/dev/null

# Check container events
kubectl describe pod <pod> | grep -A 20 Events
Enter fullscreen mode Exit fullscreen mode

Part of the Container Security Toolkit by Datanest Digital.
For support: hello@datanest.dev


This is 1 of 6 resources in the DevOps Toolkit Pro toolkit. Get the complete [Container Security Toolkit] with all files, templates, and documentation for $XX.

Get the Full Kit →

Or grab the entire DevOps Toolkit Pro bundle (6 products) for $178 — save 30%.

Get the Complete Bundle →


Related Articles

Top comments (0)