← back to blog
securityFeatured·Aug 25, 2025·12 min read

Container Security Hardening: Docker, Kubernetes & Supply Chain

Complete container security guide — Dockerfile hardening, Trivy image scanning, Kubernetes Pod Security Standards, OPA Gatekeeper, runtime security with Falco, and software supply chain with cosign + SBOM.

SJ
Sabin Joshi
DevOps Engineer
#containers#docker#kubernetes#security#trivy#falco#opa#supply-chain#sbom

Container Threat Model

Container security spans four layers: image (what's in it), registry (who can push/pull), runtime (what it can do), and supply chain (proving what you built is what deployed). Ignore any layer and you have a gap.

Dockerfile Hardening

# ❌ Insecure — common mistakes
FROM node:latest                      # mutable tag
COPY . /app                           # copies .env and secrets
RUN npm install                       # installs dev deps, runs as root
CMD ["node", "server.js"]              # runs as root

# ✅ Hardened
FROM node:20.17.0-alpine3.20          # pinned + minimal OS
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
COPY --chown=node:node src/ ./src/
USER node                             # never root
EXPOSE 3000
CMD ["node", "--max-old-space-size=256", "src/server.js"]

Image Scanning Pipeline

Container Security CI Pipeline
{arr('a','#555')}{arr('ar','#ff6b35')}{arr('ag','#00ff88')} Git Push docker build multi-stage hadolint Trivy Scan CVE + secrets CRITICAL → fail SBOM + Sign syft + cosign attest image ECR Push immutable tags scan on push Deploy sig verified BLOCK + Slack Alert PR comment + ticket

Kubernetes Pod Security Standards

Apply the restricted PSS profile to all namespaces. It enforces non-root, read-only root filesystem, dropped capabilities, and seccomp profiles.

kubectl label namespace production   pod-security.kubernetes.io/enforce=restricted   pod-security.kubernetes.io/warn=restricted

---
# Compliant pod securityContext
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  seccompProfile: { type: RuntimeDefault }
  capabilities: { drop: ["ALL"] }

Runtime Security with Falco

Falco monitors kernel syscalls to detect suspicious behavior at runtime — container spawning a shell, reading sensitive files, unexpected outbound connections. It's the IDS for your Kubernetes cluster.

# Alert if container spawns a shell
- rule: Shell spawned in container
  condition: spawned_process and container and shell_procs
  output: >
    Shell in container
    (user=%user.name img=%container.image.repository
     cmd=%proc.cmdline)
  priority: WARNING
💡Run Falco in warning-only mode for two weeks first. You'll discover legitimate behaviors (sidecar init scripts) that need allowlisting before enabling prevention mode.

Supply Chain Security with cosign

Sign images with cosign and use OPA Gatekeeper to reject pods whose images aren't signed by your CI pipeline. Even if an attacker gains registry access, they cannot deploy unsigned images.

# Sign with cosign (keyless, OIDC-based)
cosign sign   --certificate-identity=https://github.com/org/app/.github/workflows/build.yml@refs/heads/main   --certificate-oidc-issuer=https://token.actions.githubusercontent.com   $ECR/$IMAGE:$TAG

# Verify before deployment
cosign verify   --certificate-identity=...   --certificate-oidc-issuer=...   $ECR/$IMAGE:$TAG