Docker: 容器安全最佳实践
最后更新:2026-08-26
容器安全不是可选项——从镜像到运行时,每一层都需要加固。
1. 你将学到
- CIS Docker Bench 安全基线
- 镜像签名与验证(Docker Content Trust)
- 运行时安全(seccomp/AppArmor)
- Secret 安全管理策略
- 最小权限原则
2. 一个安全审计的故事
(1) 痛点:安全审计 28 项告警
Charlie 的团队收到安全审计报告:28 个告警项包括"容器以 root 运行"(高危)、"镜像有 15 个高危 CVE"(高危)、"Secret 写在环境变量里"(中危)。审计评分只有 45 分,必须修复到 80 分以上才能通过合规。
(2) 系统化安全加固的解法
Charlie 带团队一条条修复:非 root 用户、Trivy 扫描修复 CVE、Secret 改用 Docker Secret、seccomp 限制系统调用。
BASH
# Security hardening: non-root + minimal capabilities
docker run -d \
--user 1000:1000 \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--security-opt no-new-privileges \
--read-only \
myapp:1.0
(3) 收益:审计评分 45→92
系统化加固后审计评分从 45 提升到 92,所有高危项修复。
3. 容器安全层次模型
(1) 安全分层
graph TB
L6["6. Secret 管理<br/>Docker Secret / Vault"] --> L5["5. 网络安全<br/>Network isolation / TLS"]
L5 --> L4["4. 运行时安全<br/>seccomp / AppArmor / capabilities"]
L4 --> L3["3. 镜像安全<br/>扫描 / 签名 / 最小化"]
L3 --> L2["2. Docker 守护进程安全<br/>TLS / 用户权限"]
L2 --> L1["1. 主机安全<br/>OS 加固 / 内核更新"]
(1) 安全等级对照
| 等级 | 加固措施 | 效果 |
|---|---|---|
| 0 | 默认配置 | ❌ 大量告警 |
| 1 | 非 root + latest tag | ⚠️ 基础安全 |
| 2 | + 镜像扫描 + 固定版本 | ✅ 中等安全 |
| 3 | + 最小能力 + seccomp | ✅ 良好安全 |
| 4 | + DCT + Secret 管理 | ✅ 高安全 |
| 5 | + 网络隔离 + 审计日志 | ✅ 最高安全 |
4. 镜像漏洞扫描
▶ 示例:Trivy 扫描镜像(难度⭐⭐)
BASH
# Install Trivy (Linux)
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh
# Scan an image for vulnerabilities
trivy image nginx:1.25-alpine
# Scan with severity filter
trivy image --severity HIGH,CRITICAL nginx:1.25-alpine
# Scan and output JSON
trivy image --format json --output report.json myapp:1.0
💻 输出(节选):
TEXT
📖 仅展示
nginx:1.25-alpine (alpine 3.19.0)
=========================
Total: 5 (HIGH: 2, CRITICAL: 0)
┌──────────┬────────────┬──────────┬──────────┬─────────────────┐
│ Library │ Vulnerability│ Severity │ Version │ Fixed Version │
├──────────┼────────────┼──────────┼──────────┼─────────────────┤
│ libcurl │ CVE-2023-xxxx│ HIGH │ 8.4.0 │ 8.5.0 │
│ openssl │ CVE-2023-yyyy│ HIGH │ 3.1.3 │ 3.1.4 │
└──────────┴────────────┴──────────┴──────────┴─────────────────┘
▶ 示例:docker scout 扫描(难度⭐⭐)
BASH
# Docker Scout (Docker Desktop built-in)
docker scout quickview nginx:latest
# Detailed CVE report
docker scout cves nginx:latest
# Compare two images
docker scout compare --from nginx:1.24 --to nginx:1.25
5. 最小权限原则
(1) Linux Capabilities
| 能力 | 作用 | 常见需求 |
|---|---|---|
NET_BIND_SERVICE |
绑定 <1024 端口 | Web 服务(80/443) |
NET_RAW |
原始网络包 | ping / 网络调试 |
CHOWN |
修改文件所有者 | 文件管理 |
SETUID / SETGID |
切换用户 | 某些系统工具 |
ALL |
所有能力 | ❌ 不要使用 |
▶ 示例:--cap-drop 最小权限(难度⭐⭐⭐)
BASH
# Drop ALL capabilities, add only what's needed
docker run -d \
--name secure-app \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--security-opt no-new-privileges \
-p 80:8080 \
myapp:1.0
| 参数 | 作用 |
|---|---|
--cap-drop ALL |
移除所有 Linux 能力 |
--cap-add NET_BIND_SERVICE |
只添加绑定低端口的能力 |
--security-opt no-new-privileges |
禁止提权(setuid/setgid) |
--read-only |
文件系统只读(需 tmpfs 辅助) |
🔒 安全:
--privileged 给容器几乎所有主机权限——永远不要在生产环境使用。用 --cap-drop ALL + 按需 --cap-add 是最小权限原则的体现。**
6. 运行时安全
▶ 示例:seccomp 限制系统调用(难度⭐⭐⭐)
BASH
# Run with a custom seccomp profile
docker run -d \
--security-opt seccomp=chrome.json \
--name browser \
chromium:latest
(1) Docker 默认 seccomp
Docker 自带默认 seccomp 配置文件,已禁用约 44 个危险系统调用(如 mount、keyctl、add_key)。大多数应用在默认配置下可正常运行。
▶ 示例:Docker Content Trust 签名(难度⭐⭐)
BASH
# Enable DCT for the current session
export DOCKER_CONTENT_TRUST=1
# Push a signed image
docker push myorg/myapp:v1.0
# Pull: DCT verifies the signature
docker pull myorg/myapp:v1.0
# Pull unsigned image: DENIED (with DCT enabled)
docker pull myorg/myapp:unsigned
# Error: No trust data for unsigned
7. Secret 安全管理
(1) 三种 Secret 管理方式对比
| 方式 | 安全级别 | 可见性 | 适用场景 |
|---|---|---|---|
| 环境变量 (-e) | ❌ 低 | docker inspect 可见 |
开发环境 |
| Volume 文件 (-v) | ⚠️ 中 | 主机文件可见 | 过渡方案 |
| Docker Secret | ✅ 高 | 加密存储,运行时挂载 | Swarm 生产环境 |
| 外部 Vault | ✅ 最高 | 集中管理 + 审计 | 企业级 |
8. CIS Docker Benchmark
▶ 示例:docker bench security 基线检查(难度⭐⭐)
BASH
# Run CIS Docker Benchmark check
docker run --rm --net host --pid host \
--userns host --cap-drop audit_control \
-e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /etc:/etc:ro \
-v /lib/systemd/system:/lib/systemd/system:ro \
-v /usr/bin/containerd:/usr/bin/containerd:ro \
-v /usr/bin/runc:/usr/bin/runc:ro \
-v /usr/lib/systemd:/usr/lib/systemd:ro \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
docker/docker-bench-security
💻 输出(节选):
TEXT
📖 仅展示
[INFO] 1 - Host Configuration
[INFO] 1.1 - Ensure Docker is up to date
[PASS] 1.2 - Ensure only trusted users are allowed to control Docker daemon
[WARN] 1.4 - Ensure a separate partition for containers has been created
[INFO] 4 - Container Images
[PASS] 4.1 - Ensure a user for the container has been created
[WARN] 4.7 - Ensure HEALTHCHECK instructions have been added
[WARN] 4.9 - Ensure COPY is used instead of ADD
9. 完整示例:生产容器全栈加固
BASH
# ============================================
# Complete walkthrough: Production container hardening
# From audit score 45 → 92
# ============================================
# Step 1: Scan for vulnerabilities
trivy image --severity HIGH,CRITICAL myapp:1.0
# Fix: update base image, pin versions
# Step 2: Run with maximum security constraints
docker run -d \
--name hardened-app \
--user 1000:1000 \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--security-opt no-new-privileges \
--security-opt seccomp=default.json \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid \
--tmpfs /run:rw,noexec,nosuid \
-v app-logs:/app/logs \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
--health-cmd="curl -f http://localhost:8080/health || exit 1" \
--health-interval=30s \
--health-retries=3 \
-p 8080:8080 \
myapp:hardened
# Step 3: Verify security configuration
docker inspect hardened-app --format='
User: {{.Config.User}}
ReadOnly: {{.HostConfig.ReadonlyRootfs}}
Capabilities: {{.HostConfig.CapAdd}}
NoNewPrivileges: {{.HostConfig.SecurityOpt}}
'
# Step 4: Run CIS benchmark
docker run --rm ... docker/docker-bench-security
# Step 5: Re-scan after hardening
trivy image myapp:hardened
❓ 常见问题
Q Docker 容器能完全隔离吗?
A 不能。容器共享主机内核,内核漏洞可能导致容器逃逸。但容器提供了进程级隔离(namespace + cgroup + seccomp + AppArmor),大幅缩小攻击面。关键:不要用 --privileged,不要以 root 运行,及时更新内核。
Q --privileged 有什么风险?
A --privileged 赋予容器几乎所有主机权限:访问所有设备、修改内核参数、加载内核模块、绕过 seccomp/AppArmor。这基本等于在主机上直接运行程序。永远不要在生产环境使用 --privileged。
Q 镜像漏洞扫描用什么工具?
A Trivy(开源,最流行)或 Docker Scout(Docker Desktop 内置)。CI/CD 中集成:构建后自动扫描,发现 CRITICAL 漏洞时阻止部署。建议每天扫描生产镜像,新 CVE 发布后及时重建。
Q Secret 放在环境变量有什么问题?
A 三个风险:①
docker inspect 任何人都可见环境变量;② 子进程继承环境变量;③ 日志可能意外打印环境变量。Docker Secret(Swarm)加密存储,运行时挂载为临时文件,更安全。非 Swarm 环境用 HashiCorp Vault。Q rootless 模式安全吗?
A 非常安全。rootless Docker 以普通用户运行整个 Docker 守护进程,即使 Docker 本身有漏洞,攻击者也只有普通用户权限。但 rootless 模式有一些限制(无 --privileged、网络配置受限)。生产环境推荐 rootless。
📖 小节
- 容器安全六层模型:主机 → Daemon → 镜像 → 运行时 → 网络 → Secret
--cap-drop ALL+ 按需--cap-add实现最小权限原则- Trivy/Docker Scout 扫描镜像漏洞,CI 中自动阻止高危 CVE
- Docker Content Trust 签名验证,防止镜像被篡改
- Secret 不放环境变量,用 Docker Secret 或 Vault 加密管理
- CIS Docker Benchmark 是安全基线检查的标准工具
📝 作业
- 基础题(难度⭐):运行 Docker Bench Security 扫描本机,记录 WARN 级别的告警项。
- 进阶题(难度⭐⭐):用 Trivy 扫描一个已有镜像,修复所有 CRITICAL 级别的 CVE。
- 挑战题(难度⭐⭐⭐):创建一个带 seccomp 限制的容器,验证限制生效(如禁止
mount系统调用)。