使用 `docker run --security-opt` 动态加载自定义 seccomp profile

解读

在国内金融、运营商、政务云等合规场景下,**“最小权限”**是等保 2.0 与关基条例的硬性要求。
面试官问“如何动态加载自定义 seccomp”,表面考一条命令,实则验证三件事:

  1. 你是否理解 Linux seccomp 与 Docker 的协作机制
  2. 能否把合规基线(如 CIS 1.6+、工信部云原生安全指南)落地到容器运行时;
  3. 是否具备灰度调试能力:线上故障时,不重建镜像就能收紧或放宽系统调用,0 业务中断

知识点

  1. seccomp:Linux 内核特性,按系统调用号过滤,默认 Docker 用 moby/default.json 白名单 300+ 调用。
  2. --security-opt 语法
    docker run --security-opt seccomp=<路径>,路径可以是 绝对路径docker daemon 所在节点的相对路径不支持 HTTP URL,否则报 “invalid argument”。
  3. profile 格式:JSON,顶层字段 defaultActionsyscallsarchMap;国内镜像源常把 personalityptrace 等调试调用关闭,但保留 finit_module 以备自研内核模块注入。
  4. 动态加载本质:Docker 把 profile 通过 runc 写进容器的 seccomp BPF 过滤器,容器重启失效,因此可热更新而不影响镜像层。
  5. 调试利器
    • docker run --security-opt seccomp=audit.json 配合 auditd 抓取 SIGSYS
    • docker logs -f 查看 errno=EPERM 定位被拦截调用;
    • 使用 strace -ff -e trace=all 在特权侧验证缺口。
  6. 国内合规注意
    • 政务云要求 非 root + seccomp + AppArmor/SELinux 三件套
    • 金融容器云需通过 人行金融云测评,必须提供 seccomp 基线版本号变更记录
    • 若使用 龙蜥/麒麟 ARM 架构,profile 里需显式 "arch": "aarch64",否则默认 x86 导致 容器秒退

答案

  1. 本地准备自定义 profile
cat > /etc/docker/seccomp/nginx-cis.json <<'EOF'
{
  "defaultAction": "SCMP_ACT_ERRNO",
  "archMap": [
    {
      "architecture": "SCMP_ARCH_X86_64",
      "subArchitectures": ["SCMP_ARCH_X86", "SCMP_ARCH_X32"]
    }
  ],
  "syscalls": [
    {
      "names": ["accept", "bind", "clone", "close", "connect", "epoll_wait", "exit", "exit_group", "fstat", "getsockname", "listen", "read", "recvfrom", "sendto", "setgid", "setuid", "socket", "write"],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}
EOF
  1. 动态加载运行
docker run -d --name web \
  --security-opt seccomp=/etc/docker/seccomp/nginx-cis.json \
  --user 1000:1000 \
  nginx:1.25-alpine
  1. 验证
# 查看过滤器是否生效
docker exec web grep Seccomp /proc/self/status  # 输出 2 表示严格过滤
# 故意触发禁止调用
docker exec web reboot  # 返回 Operation not permitted
  1. 灰度收紧
    clone 从白名单移除 → 重跑容器 → 秒级生效,旧版本镜像无需重新打包,满足 金融灰度窗口 ≤5 分钟 的 SLA。

拓展思考

  1. 与 Kubernetes 联动
    在 1.30+ 集群,可把 profile 做成 ConfigMap,通过 SecurityContextseccompProfile.type=Localhost + localhostProfile: profiles/nginx-cis.json 注入;kubelet 自动调用 cri-dockerd 完成动态加载,实现 Pod 级热更新
  2. 多架构 CI 流水线
    在 GitLab CI 中使用 docker buildx 构建 x86 + ARM 双架构镜像时,seccomp profile 需随架构变量切换,避免 ARM 容器在 x86 白名单下启动失败。
  3. 与 eBPF LSM 结合
    国内头部云厂商已把 seccomp + eBPF LSM 做成 “二次过滤”:seccomp 做粗粒度白名单,eBPF 做 参数级细控(如 openat 路径正则),0 内核模块侵入,通过 docker run --security-opt systempaths=unconfined 关闭 AppArmor 冲突,实现 合规与性能双达标