seccomp配置必须为严格JSON格式,字段名大小写敏感且须含default_action、architectures、syscalls;架构需匹配宿主机,系统调用需保留openat等基础项;文件路径须为daemon可读的绝对路径;Go/Node.js容器需允许clone、epoll相关调用。

seccomp 配置文件必须是 JSON 格式,且字段名大小写敏感
Linux 内核的 seccomp-bpf 机制本身不认 YAML 或 TOML,Docker 只接受标准 JSON 描述的过滤规则。常见错误是手写配置时用了 defaultAction(小写 a),但正确字段名是 default_action;或者把 syscalls 写成 syscall,导致容器启动直接报错:invalid seccomp profile: unknown field "syscall"。
实操建议:
- 用
jq校验 JSON 语法:jq -n -f profile.json >/dev/null - 字段名严格按 Docker 官方 schema:必须含
default_action、architectures、syscalls -
architectures至少包含当前宿主机架构,如["SCMP_ARCH_X86_64"];漏掉会导致容器拒绝启动
只允许必要系统调用,别盲目禁用 openat 或 statx
很多精简 profile 会一刀切禁用所有文件操作,结果容器连 /proc 都读不了,ps、ls 直接失败,甚至 Go 程序因无法读取 /proc/self/exe 而 panic。真实场景里,openat 是绝大多数语言打开文件、加载动态库、读取环境配置的基础调用,禁它等于禁掉一半运行时。
实操建议:
- 先用
strace -f -e trace=raw_syscall -p $(pidof your-container-process)抓实际调用,再筛出真正需要的 - 保留
openat、read、close、statx、fstat这组最小集合,基本能跑通大多数应用 - 若需限制路径,seccomp 本身做不到——得靠
mount --bind -o ro或rootfs只读挂载配合
Docker run 时指定 seccomp 必须用绝对路径,且文件需被 daemon 读取
Docker daemon 运行在宿主机上下文,它读不到你本地 shell 当前目录下的 profile.json。常见错误是执行 docker run --security-opt seccomp=profile.json ...,结果报错:error while creating container: failed to load seccomp profile: open profile.json: no such file or directory。
实操建议:
- 配置文件必须放在 daemon 可访问路径,例如
/etc/docker/seccomp.json,然后用--security-opt seccomp=/etc/docker/seccomp.json - 确认 daemon 用户(通常是
root)对该文件有读权限:sudo chmod 644 /etc/docker/seccomp.json - 不要用
~或相对路径;./profile.json在 daemon 看来就是/profile.json
Go 和 Node.js 容器对 clone、epoll_wait 的依赖比想象中高
Go runtime 默认启用 CGO_ENABLED=1 时会调用 clone 创建线程;Node.js 的 libuv 事件循环重度依赖 epoll_wait(Linux)或 kqueue(macOS)。禁掉它们不会立刻报错,但表现为 CPU 占用飙升、HTTP 请求超时、goroutine 卡死等“软故障”,排查极难。
实操建议:
- Go 容器至少放开:
clone、epoll_ctl、epoll_wait、epoll_pwait - Node.js 容器同理,加
epoll_create1和eventfd2 - 若用 musl(Alpine)镜像,注意
clone的 flags 行为差异,建议保留SCMP_ACT_ALLOW而非SCMP_ACT_ERRNO,避免 errno 透传引发不可预知行为
docker exec -it 进去调试都会受限,因为 exec 新启的 shell 进程也受同一 profile 约束。


















