能力收敛的思路
容器默认持有一组受限但并非空集的 Linux capabilities。想做到更严格的最小权限,可以先用 --cap-drop=ALL 清空全部能力,再按需用 --cap-add 逐个放开,这比直接使用 --privileged 精确得多。核验方式是查看容器内 /proc/self/status 的 CapEff 掩码,再用能力解码工具解读出具体位含义。
基本信息
| 默认状态 | 受限的能力集合(并非空集) |
|---|---|
| 收敛写法 | --cap-drop=ALL --cap-add=NET_BIND_SERVICE |
| 核验方式 | 容器内读 /proc/self/status 的 CapEff |
| 常用按需项 | NET_BIND_SERVICE、CHOWN、SETUID、SETGID |
| 慎用项 | SYS_PTRACE、SYS_ADMIN |
典型使用场景
- 加固基线:清空能力后只放开必需项
- 排查非特权容器报 operation not permitted 时缺少哪项能力
- 容器需要直接监听 80 等低端口时放开 NET_BIND_SERVICE
- 初始化数据目录需要改属主时放开 CHOWN
- 审计存量容器,找出多余的能力放开项
清空与按需放开
清空与按需放开
docker run -d --cap-drop=ALL --cap-add=NET_BIND_SERVICE --name web nginx:1.27-alpine
docker run --rm --cap-drop=ALL alpine sh -c 'grep CapEff /proc/self/status' # 清空后的掩码
docker run --rm alpine sh -c 'grep CapEff /proc/self/status' # 默认掩码对比
docker inspect -f '{{.HostConfig.CapDrop}} {{.HostConfig.CapAdd}}' web # 核对配置能力与放开建议
| 能力 | 用途 | 放开建议 |
|---|---|---|
| NET_BIND_SERVICE | 绑定 1024 以下端口 | 仅在容器直接监听低端口时需要 |
| CHOWN | 修改文件属主 | 初始化数据目录的场景 |
| SETUID / SETGID | 切换进程用户身份 | 容器内需要降权运行时 |
| SYS_PTRACE | 进程调试与跟踪 | 仅排障期临时放开 |
| SYS_ADMIN | 大量系统管理操作 | 范围过宽,尽量不用 |
常见做法是先 drop 全部再加必需项,但放开范围必须覆盖真实运行路径,包括健康检查脚本与初始化迁移步骤。
能力配置属于创建时参数,调整需要停旧容器建新容器,改完用 inspect 核对实际生效的取值。
加固与审计做法
- 新服务默认从清空能力起步,再按运行报错逐项放开
- 放开每一项时记录原因,避免清单随复制粘贴不断膨胀
- 用检查命令定期比对存量容器的能力放开清单
- 把能力清单纳入变更评审,与权限变更一起走流程
排障思路
- 遇到权限类报错,先确认缺的是哪一项能力,再单独放开
- 放开后用真实业务路径复测,包含健康检查与初始化脚本
- 把放开的理由写在配置注释里,便于后续收敛与复核
- 定期比对各容器能力清单,清理历史遗留的过度授权