第 4 章:到底要限制什么
文件边界
从最小集合开始:只把任务输入放进去,只给输出目录写权限。不要为了方便,把整个主目录、SSH 密钥目录或所有项目映射进去。只读挂载减少修改风险,但其中的内容仍能被程序读取。
容器自己的根文件系统、临时目录、挂载目录是不同位置。你可以让根文件系统只读,同时给 /tmp 一小块临时空间,再给 /output 一个可写目录。这使“读输入、写结果”的意图更清楚。
网络边界
断网适合纯计算任务;只允许少数目标适合需要访问特定接口的任务;完全开放网络权限最大。网络政策应覆盖出口,包括 DNS、代理和重定向等实际路径,而不只是检查命令里有没有某个网址。
下载依赖和执行任务可以分成两个阶段。先在受控构建阶段准备依赖,执行时关闭网络。这有助于复现,也减少临时下载带来的变化。初学者不必一开始就搭复杂网关,但要先知道“联网”本身是一项权限。
进程和资源边界
内存限制约束主要内存使用,CPU 配额约束计算资源,进程数量限制减少无限创建进程的影响。运行时长需要额外设置:CPU 配额不会自动在三十秒后结束任务。
磁盘、输出日志、并发数和外部 API 花费也需要预算。内存限制不等于磁盘限制,限制单个任务不等于限制所有并发任务。
身份与凭证边界
非 root 用户减少进程的权限。Linux capabilities 把部分特权拆开;可以移除不需要的能力。no-new-privileges 用来阻止进程通过执行文件等途径获得新的权限。seccomp 过滤系统调用,Docker 默认配置会限制部分调用。[2][3]
这些机制互相补充,不能理解成打开一个开关就完成全部防护。凭证最好不进入沙箱;必须提供时,应短期有效、范围明确,并避免出现在命令参数或日志中。