docker-security-guide by josiahsiegel/claude-plugin-marketplace
npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill docker-security-guide强制要求:在 Windows 上始终对文件路径使用反斜杠
在 Windows 上使用编辑或写入工具时,您必须在文件路径中使用反斜杠(\),而不是正斜杠(/)。
示例:
D:/repos/project/file.tsxD:\repos\project\file.tsx这适用于:
除非用户明确要求,否则切勿创建新的文档文件。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
此技能提供了适用于所有平台的 Docker 全面安全指南,涵盖威胁、缓解措施和合规性要求。
在多个层面应用安全措施:
仅授予必要的最小权限:
威胁:易受攻击或恶意的基础镜像
缓解措施:
# 仅使用官方镜像
FROM node:20.11.0-alpine3.19 # 官方,特定版本
# 不要
FROM randomuser/node # 未经验证的来源
FROM node:latest # 不可预测,可能破坏
验证:
# 验证镜像来源
docker image inspect node:20-alpine | grep -A 5 "Author"
# 启用 Docker 内容信任(镜像签名)
export DOCKER_CONTENT_TRUST=1
docker pull node:20-alpine
威胁:更大的攻击面,更多的漏洞
缓解措施:
# 优先使用最小化发行版
FROM alpine:3.19 # ~7MB
FROM gcr.io/distroless/static # ~2MB
FROM scratch # 0MB(用于静态二进制文件)
# 对比
FROM ubuntu:22.04 # ~77MB 包含更多包
好处:
Wolfi/Chainguard 镜像:
用法:
# 开发阶段(包含构建工具)
FROM cgr.dev/chainguard/node:latest-dev AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# 生产阶段(最小化,零 CVE 目标)
FROM cgr.dev/chainguard/node:latest
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
USER node
ENTRYPOINT ["node", "server.js"]
何时使用:安全关键应用程序、合规性要求(SOC2、HIPAA、PCI-DSS)、零信任环境、强调供应链安全。
完整的镜像对比表请参见 docker-best-practices 技能。
工具:
流程:
# 使用 Docker Scout 扫描
docker scout cves IMAGE_NAME
docker scout recommendations IMAGE_NAME
# 使用 Trivy 扫描
trivy image IMAGE_NAME
trivy image --severity HIGH,CRITICAL IMAGE_NAME
# 扫描 Dockerfile
trivy config Dockerfile
# 扫描密钥
trivy fs --scanners secret .
CI/CD 集成:
# GitHub Actions 示例
- name: Scan image
run: |
docker scout cves my-image:${{ github.sha }}
trivy image --exit-code 1 --severity CRITICAL my-image:${{ github.sha }}
威胁:最终镜像中包含构建工具和密钥
缓解措施:
# 包含构建工具的构建阶段
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o app
# 最终阶段 - 最小化,无构建工具
FROM gcr.io/distroless/base-debian11
COPY --from=builder /app/app /
USER nonroot:nonroot
ENTRYPOINT ["/app"]
好处:
切勿:
# 错误 - 密钥在层历史中
ENV API_KEY=abc123
RUN git clone https://user:password@github.com/repo.git
COPY .env /app/.env
应该:
# 使用 BuildKit 密钥
# 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
# 使用密钥构建(不在镜像中)
docker build --secret id=github_token,src=./token.txt .
威胁:恶意或被入侵的 BuildKit 前端可以在构建期间执行任意代码
🚨 2025 关键警告:BuildKit 通过 # syntax= 指令支持自定义前端(解析器)。不受信任的前端具有完整的构建时代码执行能力,并且可以:
风险示例:
# 🔴 危险 - 不受信任的前端(代码执行风险!)
# syntax=docker/dockerfile:1@sha256:abc123...untrusted
FROM alpine
RUN echo "This frontend could do anything during build"
缓解措施:
# ✅ 安全 - 官方的 Docker 前端
# syntax=docker/dockerfile:1
# ✅ 安全 - 特定版本
# syntax=docker/dockerfile:1.5
# ✅ 安全 - 使用摘要固定(从 docker.com 验证)
# syntax=docker/dockerfile:1@sha256:ac85f380a63b13dfcefa89046420e1781752bab202122f8f50032edf31be0021
2. 验证前端来源:
docker/dockerfile:* 前端# 检查所有 Dockerfile 中潜在恶意的语法指令
grep -r "^# syntax=" . --include="Dockerfile*"
# 验证所有前端都是官方的 Docker 镜像
grep -r "^# syntax=" . --include="Dockerfile*" | grep -v "docker/dockerfile"
4. BuildKit 安全配置(深度防御):
# 在 BuildKit 配置中限制前端来源
# /etc/buildkit/buildkitd.toml
[frontend."dockerfile.v0"]
# 仅允许官方的 Docker 前端
allowedImages = ["docker.io/docker/dockerfile:*"]
供应链保护:
# syntax= 指令2025 年关键要求:记录所有组件的来源和历史,以实现供应链透明度和合规性。
为什么 SBOM 是强制性的:
使用 Docker Scout 生成 SBOM:
# 为镜像生成 SBOM
docker scout sbom IMAGE_NAME
# 以不同格式导出 SBOM
docker scout sbom --format spdx IMAGE_NAME > sbom.spdx.json
docker scout sbom --format cyclonedx IMAGE_NAME > sbom.cyclonedx.json
# 在构建期间包含 SBOM 证明
# ⚠️ 警告:BuildKit 证明**不是**加密签名的!
docker buildx build \
--sbom=true \
--provenance=true \
--tag my-image:latest \
.
# 查看 SBOM 证明(仅未签名的元数据)
docker buildx imagetools inspect my-image:latest --format "{{ json .SBOM }}"
🚨 关键安全限制:BuildKit 证明(--sbom=true、--provenance=true)不是加密签名的。这意味着:
使用 Syft 生成 SBOM:
# 安装 Syft
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh
# 从镜像生成 SBOM
syft my-image:latest
# 以特定格式生成
syft my-image:latest -o spdx-json > sbom.spdx.json
syft my-image:latest -o cyclonedx-json > sbom.cyclonedx.json
# 从 Dockerfile 生成
syft dir:. -o spdx-json > sbom.spdx.json
CI/CD 管道中的 SBOM:
# GitHub Actions 示例
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 最佳实践:
为每个镜像生成:
存储带有来源的 SBOM:
自动化 SBOM 生成:
使用 SBOM 进行漏洞管理:
# 扫描 SBOM 而不是镜像(更快)
grype sbom:sbom.json
trivy sbom sbom.json
# 比较版本之间的 SBOM
diff <(syft old-image:1.0 -o json) <(syft new-image:2.0 -o json)
5. SBOM 格式: * SPDX:行业标准,ISO/IEC 5962:2021 * CycloneDX:OWASP 标准,专注于安全 * 根据合规性要求选择
内置 SBOM 的 Chainguard 镜像:
# Chainguard 镜像默认包含 SBOM 证明
docker buildx imagetools inspect cgr.dev/chainguard/node:latest
# 提取 SBOM
cosign download sbom cgr.dev/chainguard/node:latest > chainguard-node-sbom.json
或者使用多阶段构建且不包含密钥:
FROM node AS builder
ARG NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc && \
npm install && \
rm .npmrc # 仍然在层历史中!
# 更好 - 密钥仅在构建阶段
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
# 最终镜像中没有 .npmrc
威胁:构建上下文中包含敏感文件
缓解措施:创建全面的 .dockerignore:
# 密钥
.env
.env.local
*.key
*.pem
credentials.json
secrets/
# 版本控制
.git
.gitignore
# 云凭据
.aws/
.gcloud/
# 私有数据
database.sql
backups/
# SSH 密钥
.ssh/
id_rsa
id_rsa.pub
# 敏感日志
*.log
logs/
启用 Docker 内容信任:
# 启用镜像签名
export DOCKER_CONTENT_TRUST=1
# 设置密钥
docker trust key generate my-key
docker trust signer add --key my-key.pub my-name my-image
# 推送已签名的镜像
docker push my-image:tag
# 仅拉取已签名的镜像
docker pull my-image:tag # 如果未签名则失败
威胁:通过 root 用户进行容器逃逸
缓解措施:
# 创建并使用非 root 用户
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"]
验证:
# 检查运行中容器内的用户
docker exec container-name whoami # 不应该是 root
docker exec container-name id # 检查 UID/GID
威胁:过多的内核能力
默认的 Docker 能力:
缓解措施:
# 丢弃所有,仅添加需要的
docker run \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
my-image
在 docker-compose.yml 中:
services:
app:
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
常见需要的能力:
NET_BIND_SERVICE:绑定到端口 < 1024NET_ADMIN:网络配置SYS_TIME:设置系统时间威胁:容器修改、恶意软件持久化
缓解措施:
docker run \
--read-only \
--tmpfs /tmp:noexec,nosuid,size=64M \
--tmpfs /var/run:noexec,nosuid,size=64M \
my-image
在 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
防止通过 setuid/setgid 二进制文件进行权限提升。
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(系统调用过滤):
# 使用默认配置文件
docker run --security-opt="seccomp=default" my-image
# 或自定义配置文件
docker run --security-opt="seccomp=./seccomp-profile.json" my-image
威胁:通过资源耗尽进行 DoS 攻击
缓解措施:
docker run \
--memory="512m" \
--memory-swap="512m" \ # 禁用交换
--cpus="1.0" \
--pids-limit=100 \
--ulimit nofile=1024:1024 \
my-image
在 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
威胁:容器之间的横向移动
缓解措施:
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 无外部访问
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
database:
networks:
- backend # 与前端隔离
威胁:不必要的网络暴露
缓解措施:
# 仅绑定到 localhost
docker run -p 127.0.0.1:8080:8080 my-image
# 不要(绑定到所有接口)
docker run -p 8080:8080 my-image
在 Compose 中:
services:
app:
ports:
- "127.0.0.1:8080:8080" # 仅限 localhost
# 禁用默认的容器间通信
# /etc/docker/daemon.json
{
"icc": false
}
然后通过网络显式允许:
services:
app1:
networks:
- app-network
app2:
networks:
- app-network # 可以与 app1 通信
networks:
app-network:
driver: bridge
# 创建密钥
echo "mypassword" | docker secret create db_password -
# 在服务中使用
docker service create \
--name my-service \
--secret db_password \
my-image
# 在容器中访问 /run/secrets/db_password
在堆栈文件中:
version: '3.8'
services:
app:
image: my-image
secrets:
- db_password
secrets:
db_password:
external: true
docker inspect 中可见)替代方案:挂载的密钥:
docker run -v /secure/secrets:/run/secrets:ro my-image
自动化检查:
# 克隆 docker-bench-security
git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security
sudo sh docker-bench-security.sh
# 或作为容器运行
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
主机配置
Docker 守护进程
Docker 文件
容器镜像
容器运行时
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "service,env"
env: "ENV,VERSION"
集中式日志记录:
services:
app:
logging:
driver: "syslog"
options:
syslog-address: "tcp://log-server:514"
tag: "{{.Name}}/{{.ID}}"
工具:
监控内容:
意外进程
文件修改
网络连接
资源峰值
失败的身份验证
权限提升尝试
docker events --filter 'type=container' --filter 'event=start'
docker events --filter "container=my-container"
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
用户命名空间重新映射:
// /etc/docker/daemon.json
{
"userns-remap": "default"
}
好处:容器中的 Root → 主机上的非特权用户
SELinux:
# 为 Docker 启用 SELinux
setenforce 1
# 使用 SELinux 标签运行
docker run --security-opt label=type:svirt_sandbox_file_t my-image
# 带有 SELinux 的卷
docker run -v /host/path:/container/path:z my-image
AppArmor:
# 检查 AppArmor 状态
aa-status
# 使用 AppArmor 配置文件运行
docker run --security-opt apparmor=docker-default my-image
Hyper-V 隔离:
# 比进程隔离更隔离
docker run --isolation=hyperv my-image
Windows Defender:
Docker Desktop 安全:
镜像:
latest)构建:
运行时:
操作:
❌ 切勿:
--privileged/var/run/docker.sock)latest 标签✅ 始终:
本安全指南代表了当前的最佳实践。安全威胁不断演变——请务必查阅最新的 Docker 安全文档和 CVE 数据库。
每周安装次数
177
仓库
GitHub 星标数
21
首次出现
2026年1月21日
安全审计
安装于
opencode147
gemini-cli141
codex140
cursor136
github-copilot129
claude-code119
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
2. Verify frontend sources:
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"
4. BuildKit security configuration (defense in depth):
# 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)
5. SBOM formats: * SPDX: Industry standard, ISO/IEC 5962:2021 * CycloneDX: OWASP standard, security-focused * Choose based on compliance requirements
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:
Unexpected processes
File modifications
Network connections
Resource spikes
Failed authentication
Privilege escalation attempts
docker events --filter 'type=container' --filter 'event=start'
docker events --filter "container=my-container"
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.
Weekly Installs
177
Repository
GitHub Stars
21
First Seen
Jan 21, 2026
Security Audits
Gen Agent Trust HubFailSocketPassSnykWarn
Installed on
opencode147
gemini-cli141
codex140
cursor136
github-copilot129
claude-code119
开发者成长分析技能:基于Claude聊天历史识别编码模式与改进领域
1,100 周安装
Python PDF处理教程:合并拆分PDF、提取文本表格、创建PDF文件
174 周安装
Claude连接1000+应用插件 - 实现邮件发送、GitHub问题创建、Slack消息发布等自动化操作
1,100 周安装
Connect技能:让Claude AI连接1000+应用执行真实操作,告别纯文本生成
1,100 周安装
Day 5 Fetch & Digest:内容获取与消化技能教程 - 学习API调用、字幕提取与Quiz-First学习法
1,100 周安装
Playwright CLI 终端浏览器自动化技能 - 无需全局安装,快速实现网页交互与测试
1,200 周安装