安全容器应“先清零、再加白”:用--cap-drop=all清除所有能力,再按需--cap-add指定如net_bind_service;配合--user、:ro、no-new-privileges等实现纵深防御,并通过capsh、/proc/1/status和ebpf持续审计。

核心思路是:不靠禁用root或删用户,而是从内核能力层精准收窄权限边界。Docker默认已丢弃多数危险能力,但真正安全的做法是主动“先清空、再加白”,而非依赖默认值。
明确容器真实需求,只加必需能力
很多容器其实根本不需要特权——比如静态网页服务只需绑定80端口,那仅添加 NET_BIND_SERVICE 就够了;日志处理容器可能只需 CHOWN 或 DAC_OVERRIDE 来修改挂载卷内文件属主。盲目保留默认能力集(如 Docker 默认启用的 CAP_CHOWN、CAP_FSETID 等)反而扩大攻击面。
- 用
capsh --print在容器内检查当前生效能力,确认是否有多余项 - 在
docker-compose.yml中显式写明所需能力,不写默认不继承 - 避免使用
--cap-add=ALL或privileged: true,这两者等同于放弃最小权限原则
启动时主动移除所有能力再按需添加
比“加白”更彻底的是“清零起步”。Docker 支持 --cap-drop=ALL 参数,它会清除所有默认能力,之后再用 --cap-add 逐个添加真正需要的能力。这种方式能杜绝因默认能力变更或镜像升级带来的隐性风险。
- 示例命令:
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE -p 80:8080 nginx:alpine - 该容器连
ping(需NET_RAW)或chown(需CHOWN)都会失败,除非你明确加上 - 适合对安全性要求极高的场景,如金融、政务类容器化服务
结合用户身份与文件系统限制进一步加固
Capability 只控制内核调用权限,还需配合其他机制形成纵深防御:
- 用
--user 1001:1001强制以非 root 用户运行,即使获得SETUID能力也无法切换到 UID 0 - 挂载卷时加
:ro标志设为只读,防止容器篡改宿主机配置文件 - 配合
--security-opt no-new-privileges:true阻止进程在运行中提权(如 execve 时 setuid 二进制)
定期审计和监控能力使用情况
生产环境中,能力配置不是一劳永逸。应用迭代可能新增系统调用需求,也可能旧功能下线后能力仍被保留。建议:
- 将
cap_add列表纳入 CI/CD 流水线检查项,禁止无说明的新增 - 在容器启动脚本中加入
cat /proc/1/status | grep CapEff,记录实际生效能力哈希值用于基线比对 - 使用 eBPF 工具(如 Tracee)监控异常 capability 使用行为,例如非网络服务进程调用
setsockoptwithSOL_SOCKET/SO_ATTACH_BPF











