Comprehensive Docker security guidelines and threat mitigation strategies
/plugin marketplace add JosiahSiegel/claude-code-marketplace/plugin install docker-master@claude-plugin-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
MANDATORY: Always Use Backslashes on Windows for File Paths
When using Edit or Write tools on Windows, you MUST use backslashes (\) in file paths, NOT forward slashes (/).
Examples:
D:/repos/project/file.tsxD:\repos\project\file.tsxThis applies to:
NEVER create new documentation files unless explicitly requested by the user.
This skill provides comprehensive security guidelines for Docker across all platforms, covering threats, mitigations, and compliance requirements.
Apply security at multiple layers:
Grant only the minimum permissions necessary:
Threat: Vulnerable or malicious base images
Mitigation:
# Use official images only
FROM node:20.11.0-alpine3.19 # Official, specific version
# NOT
FROM randomuser/node # Unverified source
FROM node:latest # Unpredictable, can break
Verification:
# Verify image source
docker image inspect node:20-alpine | grep -A 5 "Author"
# Enable Docker Content Trust (image signing)
export DOCKER_CONTENT_TRUST=1
docker pull node:20-alpine
Threat: Larger attack surface, more vulnerabilities
Mitigation:
# Prefer minimal distributions
FROM alpine:3.19 # ~7MB
FROM gcr.io/distroless/static # ~2MB
FROM scratch # 0MB (for static binaries)
# vs
FROM ubuntu:22.04 # ~77MB with more packages
Benefits:
Wolfi/Chainguard Images:
Usage:
# Development stage (includes build tools)
FROM cgr.dev/chainguard/node:latest-dev AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Production stage (minimal, zero-CVE goal)
FROM cgr.dev/chainguard/node:latest
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
USER node
ENTRYPOINT ["node", "server.js"]
When to use: Security-critical apps, compliance requirements (SOC2, HIPAA, PCI-DSS), zero-trust environments, supply chain security emphasis.
See docker-best-practices skill for full image comparison table.
Tools:
Process:
# Scan with Docker Scout
docker scout cves IMAGE_NAME
docker scout recommendations IMAGE_NAME
# Scan with Trivy
trivy image IMAGE_NAME
trivy image --severity HIGH,CRITICAL IMAGE_NAME
# Scan Dockerfile
trivy config Dockerfile
# Scan for secrets
trivy fs --scanners secret .
CI/CD Integration:
# GitHub Actions example
- name: Scan image
run: |
docker scout cves my-image:${{ github.sha }}
trivy image --exit-code 1 --severity CRITICAL my-image:${{ github.sha }}
Threat: Build tools and secrets in final image
Mitigation:
# Build stage with build tools
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o app
# Final stage - minimal, no build tools
FROM gcr.io/distroless/base-debian11
COPY --from=builder /app/app /
USER nonroot:nonroot
ENTRYPOINT ["/app"]
Benefits:
NEVER:
# BAD - Secret in layer history
ENV API_KEY=abc123
RUN git clone https://user:password@github.com/repo.git
COPY .env /app/.env
DO:
# Use BuildKit secrets
# syntax=docker/dockerfile:1
FROM alpine
RUN --mount=type=secret,id=github_token \
git clone https://$(cat /run/secrets/github_token)@github.com/repo.git
# Build with secret (not in image)
docker build --secret id=github_token,src=./token.txt .
Threat: Malicious or compromised BuildKit frontends can execute arbitrary code during build
π¨ 2025 CRITICAL WARNING: BuildKit supports custom frontends (parsers) via # syntax= directive. Untrusted frontends have FULL BUILD-TIME code execution and can:
Risk Example:
# π΄ DANGER - Untrusted frontend (code execution risk!)
# syntax=docker/dockerfile:1@sha256:abc123...untrusted
FROM alpine
RUN echo "This frontend could do anything during build"
Mitigation:
# β
Safe - Official Docker frontend
# syntax=docker/dockerfile:1
# β
Safe - Specific version
# syntax=docker/dockerfile:1.5
# β
Safe - Pinned with digest (verify from docker.com)
# syntax=docker/dockerfile:1@sha256:ac85f380a63b13dfcefa89046420e1781752bab202122f8f50032edf31be0021
docker/dockerfile:* frontends# Check all Dockerfiles for potentially malicious syntax directives
grep -r "^# syntax=" . --include="Dockerfile*"
# Verify all frontends are official Docker images
grep -r "^# syntax=" . --include="Dockerfile*" | grep -v "docker/dockerfile"
# Restrict frontend sources in BuildKit config
# /etc/buildkit/buildkitd.toml
[frontend."dockerfile.v0"]
# Only allow official Docker frontends
allowedImages = ["docker.io/docker/dockerfile:*"]
Supply Chain Protection:
# syntax= directives in Dockerfiles before buildsCritical 2025 Requirement: Document origin and history of all components for supply chain transparency and compliance.
Why SBOM is Mandatory:
Generate SBOM with Docker Scout:
# Generate SBOM for image
docker scout sbom IMAGE_NAME
# Export SBOM in different formats
docker scout sbom --format spdx IMAGE_NAME > sbom.spdx.json
docker scout sbom --format cyclonedx IMAGE_NAME > sbom.cyclonedx.json
# Include SBOM attestation during build
# β οΈ WARNING: BuildKit attestations are NOT cryptographically signed!
docker buildx build \
--sbom=true \
--provenance=true \
--tag my-image:latest \
.
# View SBOM attestations (unsigned metadata only)
docker buildx imagetools inspect my-image:latest --format "{{ json .SBOM }}"
π¨ CRITICAL SECURITY LIMITATION:
BuildKit attestations (--sbom=true, --provenance=true) are NOT cryptographically signed. This means:
Generate SBOM with Syft:
# Install Syft
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh
# Generate SBOM from image
syft my-image:latest
# Generate in specific format
syft my-image:latest -o spdx-json > sbom.spdx.json
syft my-image:latest -o cyclonedx-json > sbom.cyclonedx.json
# Generate from Dockerfile
syft dir:. -o spdx-json > sbom.spdx.json
SBOM in CI/CD Pipeline:
# GitHub Actions example
name: Build with SBOM
jobs:
build:
steps:
- name: Build image with SBOM
run: |
docker buildx build \
--sbom=true \
--provenance=true \
--tag my-image:${{ github.sha }} \
--push \
.
- name: Generate SBOM with Syft
run: |
syft my-image:${{ github.sha }} -o spdx-json > sbom.json
- name: Upload SBOM artifact
uses: actions/upload-artifact@v3
with:
name: sbom
path: sbom.json
- name: Scan SBOM for vulnerabilities
run: |
grype sbom:sbom.json --fail-on high
SBOM Best Practices:
Generate for every image:
Store SBOMs with provenance:
Automate SBOM generation:
Use SBOM for vulnerability management:
# Scan SBOM instead of image (faster)
grype sbom:sbom.json
trivy sbom sbom.json
# Compare SBOMs between versions
diff <(syft old-image:1.0 -o json) <(syft new-image:2.0 -o json)
Chainguard Images with Built-in SBOM:
# Chainguard images include SBOM attestation by default
docker buildx imagetools inspect cgr.dev/chainguard/node:latest
# Extract SBOM
cosign download sbom cgr.dev/chainguard/node:latest > chainguard-node-sbom.json
Or use multi-stage and don't include secrets:
FROM node AS builder
ARG NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc && \
npm install && \
rm .npmrc # Still in layer history!
# Better - secret only in build stage
FROM node AS dependencies
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm install
FROM node AS runtime
COPY --from=dependencies /app/node_modules ./node_modules
# No .npmrc in final image
Threat: Sensitive files included in build context
Mitigation:
Create comprehensive .dockerignore:
# Secrets
.env
.env.local
*.key
*.pem
credentials.json
secrets/
# Version control
.git
.gitignore
# Cloud credentials
.aws/
.gcloud/
# Private data
database.sql
backups/
# SSH keys
.ssh/
id_rsa
id_rsa.pub
# Sensitive logs
*.log
logs/
Enable Docker Content Trust:
# Enable image signing
export DOCKER_CONTENT_TRUST=1
# Set up keys
docker trust key generate my-key
docker trust signer add --key my-key.pub my-name my-image
# Push signed image
docker push my-image:tag
# Pull only signed images
docker pull my-image:tag # Fails if not signed
Threat: Container escape via root
Mitigation:
# Create and use non-root user
FROM node:20-alpine
RUN addgroup -g 1001 appuser && \
adduser -S appuser -u 1001 -G appuser
USER appuser
WORKDIR /home/appuser/app
COPY --chown=appuser:appuser . .
CMD ["node", "server.js"]
Verification:
# Check user in running container
docker exec container-name whoami # Should not be root
docker exec container-name id # Check UID/GID
Threat: Excessive kernel capabilities
Default Docker capabilities:
Mitigation:
# Drop all, add only needed
docker run \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
my-image
In docker-compose.yml:
services:
app:
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
Common needed capabilities:
NET_BIND_SERVICE: Bind to ports < 1024NET_ADMIN: Network configurationSYS_TIME: Set system timeThreat: Container modification, malware persistence
Mitigation:
docker run \
--read-only \
--tmpfs /tmp:noexec,nosuid,size=64M \
--tmpfs /var/run:noexec,nosuid,size=64M \
my-image
In Compose:
services:
app:
read_only: true
tmpfs:
- /tmp:noexec,nosuid,size=64M
- /var/run:noexec,nosuid,size=64M
no-new-privileges:
docker run --security-opt="no-new-privileges:true" my-image
Prevents privilege escalation via setuid/setgid binaries.
AppArmor (Linux):
docker run --security-opt="apparmor=docker-default" my-image
SELinux (Linux):
docker run --security-opt="label=type:container_runtime_t" my-image
Seccomp (syscall filtering):
# Use default profile
docker run --security-opt="seccomp=default" my-image
# Or custom profile
docker run --security-opt="seccomp=./seccomp-profile.json" my-image
Threat: DoS via resource exhaustion
Mitigation:
docker run \
--memory="512m" \
--memory-swap="512m" \ # Disable swap
--cpus="1.0" \
--pids-limit=100 \
--ulimit nofile=1024:1024 \
my-image
In Compose:
services:
app:
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
pids: 100
reservations:
cpus: '0.5'
memory: 256M
ulimits:
nofile:
soft: 1024
hard: 1024
docker run \
--name secure-app \
--detach \
--restart unless-stopped \
--user 1000:1000 \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--read-only \
--tmpfs /tmp:noexec,nosuid,size=64M \
--security-opt="no-new-privileges:true" \
--security-opt="seccomp=default" \
--memory="512m" \
--cpus="1.0" \
--pids-limit=100 \
--network=isolated-network \
--publish 127.0.0.1:8080:8080 \
--volume secure-data:/data:ro \
--health-cmd="curl -f http://localhost/health || exit 1" \
--health-interval=30s \
my-secure-image:1.2.3
Threat: Lateral movement between containers
Mitigation:
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # No external access
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
database:
networks:
- backend # Isolated from frontend
Threat: Unnecessary network exposure
Mitigation:
# Bind to localhost only
docker run -p 127.0.0.1:8080:8080 my-image
# NOT (binds to all interfaces)
docker run -p 8080:8080 my-image
In Compose:
services:
app:
ports:
- "127.0.0.1:8080:8080" # Localhost only
# Disable default inter-container communication
# /etc/docker/daemon.json
{
"icc": false
}
Then explicitly allow via networks:
services:
app1:
networks:
- app-network
app2:
networks:
- app-network # Can communicate with app1
networks:
app-network:
driver: bridge
# Create secret
echo "mypassword" | docker secret create db_password -
# Use in service
docker service create \
--name my-service \
--secret db_password \
my-image
# Access in container at /run/secrets/db_password
In stack file:
version: '3.8'
services:
app:
image: my-image
secrets:
- db_password
secrets:
db_password:
external: true
docker inspect)Alternative: Mounted secrets:
docker run -v /secure/secrets:/run/secrets:ro my-image
Automated checking:
# Clone docker-bench-security
git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security
sudo sh docker-bench-security.sh
# Or run as container
docker run --rm --net host --pid host --userns host \
--cap-add audit_control \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /usr/lib/systemd:/usr/lib/systemd:ro \
-v /etc:/etc:ro \
docker/docker-bench-security
Host Configuration
Docker Daemon
Docker Files
Container Images
Container Runtime
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "service,env"
env: "ENV,VERSION"
Centralized logging:
services:
app:
logging:
driver: "syslog"
options:
syslog-address: "tcp://log-server:514"
tag: "{{.Name}}/{{.ID}}"
Tools:
Monitor for:
# Monitor Docker events
docker events --filter 'type=container' --filter 'event=start'
# Watch specific container
docker events --filter "container=my-container"
# Runtime security with Falco
docker run --rm -it \
--privileged \
-v /var/run/docker.sock:/host/var/run/docker.sock \
-v /dev:/host/dev \
-v /proc:/host/proc:ro \
falcosecurity/falco
User namespace remapping:
// /etc/docker/daemon.json
{
"userns-remap": "default"
}
Benefits: Root in container β unprivileged on host
SELinux:
# Enable SELinux for Docker
setenforce 1
# Run with SELinux labels
docker run --security-opt label=type:svirt_sandbox_file_t my-image
# Volumes with SELinux
docker run -v /host/path:/container/path:z my-image
AppArmor:
# Check AppArmor status
aa-status
# Run with AppArmor profile
docker run --security-opt apparmor=docker-default my-image
Hyper-V isolation:
# More isolated than process isolation
docker run --isolation=hyperv my-image
Windows Defender:
Docker Desktop security:
Image:
latest)Build:
Runtime:
Operations:
β NEVER:
--privileged/var/run/docker.sock)latest tagβ ALWAYS:
This security guide represents current best practices. Security threats evolve constantlyβalways check the latest Docker security documentation and CVE databases.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.