必须使用严格JSON格式,字段名全小写带下划线(如default_action、syscalls),含architectures数组;禁用默认拒绝模式,需保留openat、read等基础调用;路径须为daemon可读的绝对路径;高危调用按场景选SCMP_ACT_ERRNO或SCMP_ACT_KILL。

直接启用自定义 Seccomp 策略不是加个 --security-opt 就完事——90% 的失败都卡在 JSON 格式、路径权限或基础调用误禁上。
seccomp.json 必须是严格 JSON,字段名大小写不能错
Docker 只认标准 JSON,且字段名完全大小写敏感。写成 defaultAction 或 syscall 会直接报错:invalid seccomp profile: unknown field "syscall"。
- 必须用
default_action(下划线,全小写),不是defaultAction - 必须用
syscalls(复数),不是syscall - 必须包含
architectures字段,例如["SCMP_ARCH_X86_64"];漏掉会导致容器启动失败 - 建议用
jq -n -f profile.json >/dev/null预校验语法
别盲目设 "default_action": "SCMP_ACT_ERRNO"
设成默认拒绝再白名单放行,听起来安全,但实际会让大多数应用直接崩溃——Go 程序连 /proc/self/exe 都读不了,Node.js 进程起不来,ls、ps 全挂。
- 先用
strace -f -e trace=raw_syscall -p $(pidof your-app)抓真实调用流 - 至少保留这组基础调用:
openat、read、close、statx、fstat、epoll_wait、clone - Go 和 Node.js 容器对
clone和epoll_wait依赖极强,禁掉就 panic 或 hang 住
docker run 里 --security-opt seccomp= 的路径必须绝对且 daemon 可读
./seccomp.json 或 ~/profile.json 在 Docker daemon 看来就是不存在的路径,会报:open profile.json: no such file or directory。
- 文件必须放在 daemon 能访问的位置,比如
/etc/docker/seccomp.json - 确认权限:运行
sudo chmod 644 /etc/docker/seccomp.json,确保root(daemon 用户)可读 - 命令中必须写绝对路径:
--security-opt seccomp=/etc/docker/seccomp.json - 不要用
docker build阶段 copy 进镜像——Seccomp 是 runtime 行为,只在docker run时加载
高危系统调用拦截要分场景选 action
不是所有危险调用都该 SCMP_ACT_KILL。粗暴杀进程可能掩盖问题,也影响可观测性。
-
ptrace:建议用SCMP_ACT_ERRNO,返回EPERM,不中断进程,便于日志捕获 -
mount、chroot:可用SCMP_ACT_KILL,这类调用一旦发生基本就是逃逸尝试 -
capset:必须禁,且推荐SCMP_ACT_ERRNO,避免因能力检查失败导致程序异常退出 - 注意:
names是数组,即使只禁一个也要写成"names": ["ptrace"]
真正难的不是写规则,而是判断哪些调用是“业务必需”、哪些是“历史残留”——没有 strace 实测的 profile,都是纸上谈兵。


















