第11章:Docker 安全加固

第11章:Docker 安全加固

本章目标:理解 Docker 的安全威胁和攻击面,掌握容器安全加固的最佳实践。


11.1 Docker 安全威胁概览

11.1.1 容器安全的四个维度

复制代码
┌────────────────────────────────────────────────────────┐
│                 Docker 安全威胁模型                      │
│                                                        │
│  1. 镜像安全                    2. 运行时安全           │
│  ┌──────────────────┐          ┌──────────────────┐   │
│  │ - 恶意基础镜像    │          │ - 容器逃逸        │   │
│  │ - 漏洞依赖包     │          │ - 资源耗尽        │   │
│  │ - 硬编码密钥     │          │ - 未授权访问       │   │
│  │ - 过多的权限     │          │ - 进程注入        │   │
│  └──────────────────┘          └──────────────────┘   │
│                                                        │
│  3. 网络安全                    4. 编排安全             │
│  ┌──────────────────┐          ┌──────────────────┐   │
│  │ - 网络隔离不足    │          │ - API 未授权访问   │   │
│  │ - 端口暴露       │          │ - 密钥管理不当     │   │
│  │ - 中间人攻击     │          │ - 配置泄露        │   │
│  │ - DNS 劫持       │          │ - 权限过大        │   │
│  └──────────────────┘          └──────────────────┘   │
└────────────────────────────────────────────────────────┘

11.1.2 常见攻击类型

攻击类型 描述 危害等级
容器逃逸 从容器突破隔离获取宿主机权限 ⭐⭐⭐⭐⭐
恶意镜像 使用包含后门的基础镜像 ⭐⭐⭐⭐
漏洞利用 利用镜像中的已知漏洞 ⭐⭐⭐
密钥泄露 镜像中包含硬编码的密码/密钥 ⭐⭐⭐
资源耗尽 容器消耗过多系统资源 ⭐⭐
横向移动 从一个容器攻击其他容器 ⭐⭐⭐

11.2 镜像安全

11.2.1 使用可信的基础镜像

dockerfile 复制代码
# ✅ 使用官方镜像(经过验证)
FROM ubuntu:22.04
FROM python:3.11-slim
FROM node:20-alpine

# ✅ 使用 distroless 镜像(Google 的安全镜像)
FROM gcr.io/distroless/python3-debian12
FROM gcr.io/distroless/java17-debian12

# ❌ 避免使用未知来源的镜像
FROM random-user/custom-image:latest

# ✅ 使用特定标签而非 latest
FROM nginx:1.25.3-alpine  # 指定版本
# ❌ FROM nginx:latest     # 版本不可控

11.2.2 镜像安全扫描

bash 复制代码
# 使用 Docker Scout 扫描
docker scout cves nginx:latest
docker scout recommendations nginx:latest

# 使用 Trivy 扫描
trivy image --severity HIGH,CRITICAL nginx:latest

# 在 CI/CD 中集成扫描
# 扫描失败则停止构建
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest

11.2.3 镜像签名与验证

bash 复制代码
# 启用 Docker Content Trust
export DOCKER_CONTENT_TRUST=1

# 推送时自动签名
docker push myregistry.com/myapp:v1.0

# 拉取时自动验证
docker pull myregistry.com/myapp:v1.0

11.2.4 多阶段构建减少攻击面

dockerfile 复制代码
# ✅ 多阶段构建:构建工具不进入最终镜像
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o server .

FROM scratch
COPY --from=builder /app/server /server
ENTRYPOINT ["/server"]

# 最终镜像只有静态二进制,没有 shell、包管理器等

11.3 运行时安全

11.3.1 不要使用 root 用户

dockerfile 复制代码
# ✅ 创建并使用非 root 用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser

# 或使用现有用户
USER nobody:nogroup
bash 复制代码
# 验证容器是否以 root 运行
docker exec <container> whoami
# root → ❌ 不安全
# appuser → ✅ 安全

# 查看容器进程的用户
docker exec <container> ps aux
# root     1  ...  → ❌ 主进程是 root
# appuser  1  ...  → ✅ 主进程是非 root

11.3.2 只读文件系统

bash 复制代码
# 使用只读文件系统
docker run -d --read-only nginx

# 需要写入的目录使用 tmpfs
docker run -d --read-only \
  --tmpfs /tmp \
  --tmpfs /var/run \
  nginx

11.3.3 禁用特权模式

bash 复制代码
# ❌ 绝不要使用 --privileged
docker run --privileged nginx  # 危险!

# ✅ 使用最小权限
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx

# 查看容器的 capabilities
docker inspect --format='{{.HostConfig.CapAdd}}' <container>

11.3.4 资源限制

bash 复制代码
# 限制 CPU 和内存,防止资源耗尽攻击
docker run -d \
  --cpus="1" \
  --memory="512m" \
  --memory-swap="512m" \
  --pids-limit=100 \
  nginx

# 参数说明:
# --cpus         限制 CPU 核数
# --memory       限制内存
# --memory-swap  限制 swap(设为与 memory 相同可禁用 swap)
# --pids-limit   限制进程数(防止 fork bomb)

11.3.5 禁用不需要的能力

bash 复制代码
# 删除所有 capabilities,按需添加
docker run -d \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  nginx

# 常用 capabilities:
# NET_BIND_SERVICE  绑定低端口
# CHOWN             修改文件所有者
# SETUID/SETGID     设置用户/组 ID
# SYS_PTRACE        调试进程(生产禁用)

11.4 网络安全

11.4.1 最小化端口暴露

bash 复制代码
# ✅ 只暴露必要的端口
docker run -d -p 80:80 nginx

# ❌ 不要暴露管理端口
# docker run -d -p 8080:8080 admin-panel  # 如果不需要外部访问

# ✅ 限制绑定地址
docker run -d -p 127.0.0.1:8080:80 nginx  # 只允许本机访问

11.4.2 网络隔离

bash 复制代码
# ✅ 使用自定义网络隔离服务
docker network create frontend
docker network create backend

docker run -d --name nginx --network frontend nginx
docker run -d --name app --network backend myapp
docker run -d --name db --network backend mysql

# 将 nginx 连接到 backend(作为代理)
docker network connect backend nginx

# ❌ 不要让数据库直接暴露到前端网络

11.4.3 DNS 安全

bash 复制代码
# 自定义 DNS 配置
docker run -d \
  --dns 8.8.8.8 \
  --dns-search "" \
  nginx

# 避免使用宿主机的 DNS 配置(可能泄露内部域名)

11.5 密钥管理

11.5.1 不要在镜像中存储密钥

dockerfile 复制代码
# ❌ 绝对不要这样做!
ENV DATABASE_PASSWORD=secret123
COPY .env /app/.env
COPY cert.pem /app/cert.pem

# ✅ 使用 Docker Secrets(Swarm 模式)
# ✅ 使用环境变量(运行时注入)
# ✅ 使用外部密钥管理服务(Vault 等)

11.5.2 Docker Secrets

yaml 复制代码
# docker-compose.yml
version: '3.8'

services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

11.5.3 BuildKit Secret Mount

dockerfile 复制代码
# 在构建时使用 secret(不会保留在镜像层中)
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
    npm install
bash 复制代码
# 构建时传递 secret
docker build --secret id=npmrc,src=.npmrc -t myapp .

11.6 Docker Daemon 安全

11.6.1 限制 Docker Socket 访问

bash 复制代码
# Docker Socket 权限
ls -la /var/run/docker.sock
# srw-rw---- 1 root docker 0 ... /var/run/docker.sock

# ⚠️ 任何可以访问 Docker Socket 的用户等同于 root 权限!
# 不要将 Docker Socket 挂载到容器中(除非绝对必要)

# ❌ 危险:挂载 Docker Socket
docker run -v /var/run/docker.sock:/var/run/docker.sock docker

# ✅ 如果必须访问 Docker API,使用代理

11.6.2 启用审计日志

bash 复制代码
# 配置 Docker Daemon 审计
# /etc/docker/daemon.json
{
  "debug": false,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "5"
  }
}

# 使用 auditd 监控 Docker 相关文件
auditctl -w /var/run/docker.sock -p rwxa -k docker
auditctl -w /usr/bin/docker -p rwxa -k docker
auditctl -w /etc/docker -p rwxa -k docker

11.6.3 限制容器的系统调用

bash 复制代码
# 使用 seccomp 配置文件限制系统调用
docker run -d --security-opt seccomp=custom-profile.json nginx

# 使用默认的 seccomp 配置
docker run -d --security-opt seccomp=default nginx

# 禁用 seccomp(不推荐)
docker run -d --security-opt seccomp=unconfined nginx

11.6.4 使用 AppArmor/SELinux

bash 复制代码
# AppArmor(Ubuntu/Debian)
docker run -d --security-opt apparmor=docker-default nginx

# SELinux(CentOS/RHEL)
docker run -d --security-opt label=level:s0:c100,c200 nginx

11.7 安全基线检查

11.7.1 Docker Bench Security

bash 复制代码
# 运行 Docker Bench Security 检查
docker run --rm --net host --pid host \
  --userns host --cap-add audit_control \
  -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
  -v /var/lib:/var/lib:ro \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  -v /usr/lib/systemd:/usr/lib/systemd:ro \
  docker/docker-bench-security

# 输出安全评分和建议

11.7.2 安全检查清单

bash 复制代码
# 检查清单:

# 1. 镜像安全
docker images --format "{{.Repository}}:{{.Tag}}" | while read img; do
  echo "检查 $img ..."
  trivy image --severity HIGH,CRITICAL "$img" 2>/dev/null | head -20
done

# 2. 运行容器安全
docker ps --format "{{.Names}}" | while read container; do
  echo "检查 $container ..."
  # 检查是否以 root 运行
  docker exec "$container" whoami 2>/dev/null
  # 检查特权模式
  docker inspect --format='{{.HostConfig.Privileged}}' "$container"
done

# 3. 网络安全
docker ps --format "{{.Names}}:{{.Ports}}"

11.8 安全加固最佳实践

11.8.1 Dockerfile 安全清单

复制代码
✅ Dockerfile 安全最佳实践:

1. 使用可信的基础镜像
2. 使用特定版本标签(非 latest)
3. 使用多阶段构建
4. 使用非 root 用户运行
5. 使用只读文件系统
6. 不要在镜像中存储密钥
7. 定期扫描镜像漏洞
8. 使用 .dockerignore 排除敏感文件
9. 添加 HEALTHCHECK 健康检查
10. 使用 LABEL 添加安全信息

11.8.2 运行时安全清单

复制代码
✅ 运行时安全最佳实践:

1. 使用 --security-opt=no-new-privileges
2. 使用 --cap-drop ALL --cap-add <needed>
3. 使用 --read-only --tmpfs /tmp
4. 限制资源:--cpus --memory --pids-limit
5. 不要使用 --privileged
6. 不要挂载 Docker Socket
7. 使用自定义网络隔离
8. 只暴露必要的端口
9. 定期更新镜像
10. 监控容器行为

11.8.3 完整的安全加固示例

bash 复制代码
# 安全加固的容器运行示例
docker run -d \
  --name secure-app \
  --user 1000:1000 \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  --security-opt no-new-privileges:true \
  --security-opt seccomp=default \
  --cpus="1" \
  --memory="256m" \
  --memory-swap="256m" \
  --pids-limit=50 \
  --network app-network \
  -p 8080:80 \
  --health-cmd "curl -f http://localhost/ || exit 1" \
  --health-interval 30s \
  --restart unless-stopped \
  myapp:latest

11.9 动手实验

实验 11.1:安全扫描

bash 复制代码
# 1. 扫描官方镜像
trivy image nginx:latest
trivy image python:3.11-slim
trivy image node:20-alpine

# 2. 对比不同基础镜像的安全性
trivy image --severity HIGH,CRITICAL ubuntu:22.04
trivy image --severity HIGH,CRITICAL ubuntu:22.04-minimal
trivy image --severity HIGH,CRITICAL alpine:3.19

# 3. 扫描你自己的镜像
docker build -t myapp:latest .
trivy image myapp:latest

实验 11.2:安全运行

bash 复制代码
# 1. 对比普通运行和安全运行
# 普通运行
docker run -d --name insecure nginx
docker exec insecure whoami  # root ❌

# 安全运行
docker run -d --name secure \
  --user 1000:1000 \
  --read-only \
  --tmpfs /tmp \
  --cap-drop ALL \
  --security-opt no-new-privileges:true \
  nginx
docker exec secure whoami  # nginx ✅

# 2. 验证只读文件系统
docker exec secure touch /test.txt
# touch: cannot touch '/test.txt': Read-only file system ❌

实验 11.3:Docker Bench Security

bash 复制代码
# 运行安全基线检查
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 \
  docker/docker-bench-security

# 分析输出,修复发现的问题

11.10 本章小结

安全维度 关键措施
镜像安全 使用可信镜像、扫描漏洞、签名验证
运行时安全 非 root 用户、只读文件系统、最小权限
网络安全 网络隔离、端口最小化、DNS 安全
密钥管理 不存储在镜像、使用 Secrets、外部管理
Daemon 安全 限制 Socket 访问、审计日志、seccomp

11.11 课后练习

  1. 检查题:使用 Docker Bench Security 检查你的 Docker 环境,修复发现的问题。
  2. 实践题:为你的应用编写安全加固的 Dockerfile 和运行命令。
  3. 研究题:了解容器逃逸的原理和防护措施。

📖 下一章:Docker 监控与日志 ------ 搭建容器可观测性体系

相关推荐
分布式存储与RustFS1 小时前
RustFS保姆级教程:Docker快速部署兼容S3的本地对象存储
运维·docker·容器·rustfs部署教程·本地搭建s3对象存储·rustfs网页控制台使用·awscli连接rustfs
江湖有缘1 小时前
Docker部署Papra极简文件归档平台
运维·docker·容器
gooxi_hui2 小时前
海量存力,智驭未来丨国鑫4U60盘位高密度存储服务器SL401-G4重磅上市
运维·服务器·人工智能
微信开发api-视频号协议2 小时前
Codex++安全边界探秘:从模型能力到风险防御
前端·安全·微信·企业微信
吴爃2 小时前
小微企业 SRE 稳定性建设
运维·稳定性·小微企业
明理的路灯2 小时前
安装 git 开发工具
git
枝头玉2 小时前
新160个CrackMe048-monkeycrackme1、049-THraw-crackme8、050-daxxor逆向分析
安全·逆向·crackme·reserve
小弥儿2 小时前
GitHub今日热榜 | 2026-07-04
学习·开源·github
开开心心_Every2 小时前
带OCR识别的电子发票打印工具
运维·自动化·ocr·电脑·powerpoint·音视频·lua
小张成长计划..2 小时前
【Linux】7:第一个系统程序-进度条
linux·运维·服务器