Help us improve
Share bugs, ideas, or general feedback.
From grimoire
Hardens Docker containers against privilege escalation, image vulnerabilities, and container escape using non-root users, minimal base images, and security profiles.
npx claudepluginhub jeffreytse/grimoire --plugin grimoireHow this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:apply-docker-securityThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Harden Docker containers by running as non-root, using read-only filesystems, scanning images for vulnerabilities, and applying seccomp/AppArmor profiles — preventing privilege escalation and container escape.
Hardens Docker/container images and runtime deployments with secure base images, non-root users, CVE scanning, SBOM/signing, seccomp/AppArmor, and Kubernetes pod security controls.
<!-- AUTO-GENERATED by export-plugins.py — DO NOT EDIT -->
Hardens Docker container images using multi-stage builds, distroless bases, non-root users, and CIS Benchmark to minimize attack surface for production deployments.
Share bugs, ideas, or general feedback.
Harden Docker containers by running as non-root, using read-only filesystems, scanning images for vulnerabilities, and applying seccomp/AppArmor profiles — preventing privilege escalation and container escape.
Adopted by: OWASP Docker Security Cheat Sheet and CIS Docker Benchmark (Center for Internet Security) are the two authoritative references. NIST SP 800-190 (Application Container Security Guide, 2017) provides federal guidance. Google Cloud, AWS ECS, and Azure Container Apps all enforce non-root and read-only filesystem policies in their hardened runtime configurations. Kubernetes Pod Security Standards (baseline/restricted) mandate non-root and non-privileged containers.
Impact: Container escape vulnerabilities (CVE-2019-5736 runc, CVE-2020-15257 containerd) allow processes inside containers to gain host-level access — most exploitable when the container runs as root. The 2021 Codecov supply chain attack used compromised Docker images in CI pipelines to steal credentials from thousands of organizations. Trivy and Snyk Container scans find high/critical CVEs in 60%+ of production images according to Snyk's State of Open Source Security 2023.
Why best: Running containers with the --privileged flag or as root with volume mounts to / is equivalent to running on the host with sudo. Rootless containers, read-only filesystems, and capability dropping eliminate entire classes of container escape and privilege escalation attacks with minimal operational overhead.
Sources: OWASP Docker Security Cheat Sheet; CIS Docker Benchmark v1.6; NIST SP 800-190; CWE-250
Run as a non-root user — never use USER root in production images:
FROM node:20-alpine
# Create a non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --chown=appuser:appgroup . .
RUN npm ci --production
# Drop to non-root before CMD
USER appuser
CMD ["node", "server.js"]
For existing images that default to root: override with --user 1000:1000 at runtime.
Use minimal base images — reduce attack surface by minimizing installed packages:
# Alpine: ~5MB, minimal attack surface
FROM python:3.12-alpine
# Distroless: no shell, no package manager, minimal CVE surface
FROM gcr.io/distroless/python3:nonroot
# Multi-stage: build dependencies stay in builder, only runtime artifacts in final
FROM python:3.12-alpine AS builder
COPY requirements.txt .
RUN pip install --prefix=/install -r requirements.txt
FROM gcr.io/distroless/python3:nonroot
COPY --from=builder /install /usr/local
COPY app.py .
CMD ["app.py"]
Make the filesystem read-only — prevent runtime file modification:
# Docker CLI
docker run --read-only --tmpfs /tmp --tmpfs /run myapp
# Docker Compose
services:
app:
read_only: true
tmpfs:
- /tmp
- /var/run
# Kubernetes pod spec
securityContext:
readOnlyRootFilesystem: true
Drop all capabilities and add only what's needed:
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp
# Kubernetes
securityContext:
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE"] # only if binding port <1024
Most apps need zero Linux capabilities — run on port ≥1024 to avoid even NET_BIND_SERVICE.
Scan images for vulnerabilities in CI:
# Trivy (recommended — free, comprehensive)
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest
# Grype
grype myapp:latest --fail-on high
# In CI (GitHub Actions):
- uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
exit-code: '1'
severity: 'HIGH,CRITICAL'
Never pass secrets as environment variables or build args:
# BAD — secrets visible in image history
ARG DATABASE_URL
ENV DATABASE_URL=${DATABASE_URL}
# GOOD — use runtime secret mounts
# Docker BuildKit secret mount (available at build time, not stored in image):
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm install
At runtime: use Docker secrets, Kubernetes Secrets (ideally from a Secrets Manager), or environment injection from a vault.
Apply seccomp and AppArmor profiles — restrict syscall surface:
# Use Docker's default seccomp profile (denies 44 dangerous syscalls)
docker run --security-opt seccomp=default.json myapp
# Kubernetes: enforce restricted pod security standard
# Add label to namespace:
kubectl label namespace production pod-security.kubernetes.io/enforce=restricted
--privileged in production — it gives the container all Linux capabilities and disables seccomp/AppArmor./var/run/docker.sock) inside a container — it gives full host access.FROM node:20-alpine@sha256:... prevents supply chain attacks via tag mutation.no-new-privileges: true to prevent setuid binaries from escalating inside the container.FROM ubuntu:latest as base image — includes hundreds of unnecessary packages, each a potential CVE..env files copied into the image — visible in docker history and image layers.