容器安全 — 供应链、镜像信任、加固与运行时防线¶
这一章的全景: 一个漏洞或一次错误配置,就能让整个环境失守——所以安全不是 某个工具,是全生命周期的防线。书里把它分成四层,本章按四层讲: 供应链(镜像从哪来、有没有被动过)→ 加固(容器里能做什么被限制到最小)→ secrets(密钥怎么进场)→ 运行时(跑起来之后谁盯着)。 每一层都给了"收益 vs 代价"的对照,这是本章最诚实的地方。
1. 供应链安全:镜像的来路¶
攻击面从构建之前就开始了。供应链层的三件套1:
- 用可信的基础镜像——官方镜像、验证过的发布者;
- 扫描——Trivy、Clair、Docker Scout 对照 CVE 库查已知漏洞(装 Trivy 可直接 用各平台包管理器或官方二进制;cosign 同理)2;
- 签名与验证——cosign 生成密钥对(
cosign generate-key-pair)、 给推上注册表的镜像签名;签名要先于验证,镜像要先推后签,且别用 latest 这种 浮动标签3。
三层要叠成纵深防御(defense in depth):管道里要求验证签名;部署时 (Kubernetes 准入控制器、Connaisseur、Gatekeeper 策略)只放行签过名的镜像; 注册表层(Harbor + Cosign)可以要求"没签名不准拉"。哪怕一个漏洞漏网, 未签名或被篡改的镜像也进不了生产4。
2. 加固:把容器收紧到最小权限¶
加固(hardening)的定义:收紧设备、文件系统、权限与运行时约束,缩小攻击面、 降低出事时的损害5。书里给的清单,逐条接住:
非 root + 裁剪 capability。 很多官方镜像默认容器内 root——进程一旦逃逸或被攻破,
root 权限给了它太多杠杆。Dockerfile 里 groupadd -r/useradd -r 建系统用户、
改文件属主、USER appuser 收尾;运行时再 --cap-drop ALL 先清空、
--cap-add 只加真正需要的(比如 NET_BIND_SERVICE 绑低端口)6。
--no-new-privileges 封死提权:就算进程想通过 setuid 或内核漏洞拿新权限也拿不到
(macOS 上用 --security-opt no-new-privilege:true 变体)6。
只读文件系统与最小挂载。 --read-only 把整个根文件系统变只读,
写操作只剩显式挂出来的目录(日志、tmp、上传各挂一个空卷)。
镜像侧:slim/Alpine 基底、distroless(无 shell 无包管理器)、多阶段构建把编译器
和构建缓存永远挡在最终镜像外7。
内核级安全机制。 会用才算会用容器:
seccomp 过滤系统调用(Docker 默认带一个限制危险调用的 profile,可自定义
default.json);AppArmor/SELinux 给容器配安全策略,限制文件系统与资源访问;
user namespace 把容器内 UID 重映射为宿主机非 root UID,逃逸了也拿不到什么;
还有几条铁律:非必要绝不 --privileged;--icc=false 禁止容器间默认互访8。
资源限额。 --memory、--cpus、--pids-limit、--ulimit:
防资源耗尽型 DoS(第 08 章的 cgroup 驾驶舱在这里是安全工具)9。
可检测、可替换。 Dockerfile 里加 HEALTHCHECK(--interval=30s --timeout=5s
--start-period=5s --retries=3),让编排器能把不健康容器标出来重启;
被攻破或生病的容器直接换掉,不打补丁——不可变基础设施的心态10。
组合示例(hardened baseline):
$ docker run --rm -p 4567:4567 \
--read-only \
--cap-drop ALL --cap-add NET_BIND_SERVICE \
--no-new-privileges \
--memory 256m --cpus 0.5 \
hello-ruby:latest
→ 只读根fs、最小 capability、禁提权、CPU/内存限额、非 root——"a strong
baseline you can build on"(书中原话)[^11]
代价表(本章最有价值的一张表)。 加固每加一条,都可能碰灵活性、性能或开发便利: capability 裁狠了,绑低端口这类正常操作也会失败;只读文件系统会让"顺手写个临时文件" 的程序报错;distroless 没有 shell,调试变难。做法是先精确盘点应用真正需要什么, 再按环境选平衡点——安全收益和代价要一起看,不是越多越好12。
3. Secrets:密钥怎么进场¶
红线(第 04、08 章已埋伏笔,这里收拢):密码、API key 绝不硬编码、绝不进镜像、 尽量不进环境变量(环境变量对任何能 inspect 容器的人可见)。 正确姿势:运行期从加密存储取(云厂的 Secrets Manager / Vault),或(书里演示的 Docker 做法)用 secrets 机制挂载——secret 被装进 /run/secrets/ 下的文件, 应用从文件读(DB_PASSWORD_FILE 指向路径),compose 里声明,容器外的人看不见明文13。
4. 运行时安全:Falco 们看住"不该发生的事"¶
静态防线都就位后,最后一层是行为监控:Falco(以及 Sysdig)监听容器内 的系统调用,规则命中就告警——典型规则:web 容器里突然起了个 shell、 进程读写它不该碰的路径、出现意料外的网络连接。这类"运行时检出"补的是 静态扫描的盲区:配置全对,也挡不住有人利用合法配置干坏事14。 (第 12 章的安全监控一节预告过它;在 Kubernetes 里它通常以 DaemonSet 形式 看住每个节点。)
5. 作者的判断与证据¶
- "扫描 + 签名 + 执行"三层纵深是本章的核心架构判断, 一句原文值得记住:"even if a vulnerability slips through, an unsigned or tampered image cannot enter production"4。
- 加固清单全部有实操命令(非 root、cap-drop、--read-only、--no-new-privileges、 seccomp、资源限额),且给了组合基线611——证据强度高于一般"最佳实践"罗列。
- 代价表是诚实的:每条加固都列出 Potential Downsides 与 Mitigation, 没有假装安全免费12。
- 工具名单(Trivy、cosign、Connaisseur、Gatekeeper、Falco)是 2026 年主流, 会随生态漂移。
判断(我们的,不是书里的): 本章四层防线对应一句话:"默认不信,处处留证"—— 镜像不信(扫描+签名)、进程不信(最小权限+只读)、配置不信(secrets 加密)、 行为不信(运行时监控)。这四层与 12 章的可观测性叠起来,才构成完整闭环: 防线挡不住的,至少要看得见。 如果错,会错在: 对资源充足的大厂,四层全建是常态;但对小团队, 四层全建的成本可能超过业务风险——本书没给"按威胁建模裁剪"的决策框架, 这是读者要自己补的一课。
6. 边界与局限¶
- 签名/准入的配置依赖 Kubernetes(Connaisseur、Gatekeeper)——单机 Docker 场景里"执行"层要靠注册表(Harbor)或脚本补齐,书里以 K8s 为主语。
- seccomp/AppArmor/SELinux 只给了入口,各写一套可用策略是专门的学问; 盲目套 default profile 也可能让正常应用报错。
- Falco 一节偏概念,规则编写、告警路由、误报治理未展开。
- macOS 上
--no-new-privileges的替代写法这类平台细节散在各处。
7. 可带走的¶
- 供应链三件套:可信镜像 + 扫描(Trivy/Scout)+ 签名(cosign), 扫描/签名/执行三层纵深14。
- 签名先于验证、先推后签、不用浮动标签3。
- 加固清单:非 root、cap-drop ALL + 按需 cap-add、--no-new-privileges、 --read-only + 最小写挂载、slim/distroless/多阶段、seccomp/AppArmor/SELinux/ user namespace、资源限额、HEALTHCHECK678910。
- 组合基线命令照抄可用(--read-only --cap-drop ALL --no-new-privileges --memory --cpus)11。
- 加固有代价:按应用真实需求盘点,再选平衡点12。
- secrets 走 /run/secrets 挂载或外部加密存储,绝不见明文13。
- 运行时靠 Falco/Sysdig 看行为,补静态防线之盲区14。
8. 原文地图¶
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 攻击面与全生命周期立场 | Chapter 13: Securing Containers | text/144-ch13-chapter-13-securing-containers.txt:4(搜「attack surface」) |
| 三层纵深(扫描/签名/执行) | Container hardening practices | text/147-fm-container-hardening-practices.txt:1(搜「signature verification」) · text/147-fm-container-hardening-practices.txt:3(搜「admission controllers」) · text/147-fm-container-hardening-practices.txt:8(搜「defense-in-depth」) |
| 加固定义与清单 | Container hardening practices | text/147-fm-container-hardening-practices.txt:13(搜「Container hardening」) · text/147-fm-container-hardening-practices.txt:17(搜「tightening」) |
| 非 root 与 capability | Container hardening practices | text/147-fm-container-hardening-practices.txt:28(搜「least privilege」) · text/147-fm-container-hardening-practices.txt:40(搜「groupadd」) · text/147-fm-container-hardening-practices.txt:58(搜「cap-drop ALL」) · text/147-fm-container-hardening-practices.txt:67(搜「don't include it」) |
| --no-new-privileges | Container hardening practices | text/147-fm-container-hardening-practices.txt:68(搜「no-new-privileges」) · text/147-fm-container-hardening-practices.txt:79(搜「simple but powerful」) |
| 只读文件系统与最小挂载 | Container hardening practices | text/147-fm-container-hardening-practices.txt:93(搜「read-only」) · text/147-fm-container-hardening-practices.txt:110(搜「logs」) |
| 最小镜像与多阶段 | Container hardening practices | text/147-fm-container-hardening-practices.txt:113(搜「minimal images」) · text/147-fm-container-hardening-practices.txt:118(搜「distroless」) · text/147-fm-container-hardening-practices.txt:126(搜「intermediate layers」) |
| seccomp/AppArmor/SELinux/userns | Container hardening practices | text/147-fm-container-hardening-practices.txt:129(搜「Kernel-level」) · text/147-fm-container-hardening-practices.txt:135(搜「seccomp」) · text/147-fm-container-hardening-practices.txt:137(搜「AppArmor」) · text/147-fm-container-hardening-practices.txt:140(搜「User namespaces」) · text/147-fm-container-hardening-practices.txt:143(搜「privileged」) · text/147-fm-container-hardening-practices.txt:146(搜「icc=false」) |
| 资源限额作为安全手段 | Container hardening practices | text/147-fm-container-hardening-practices.txt:158(搜「Resource limits」) · text/147-fm-container-hardening-practices.txt:166(搜「denial-of-service」) |
| HEALTHCHECK 与不可变替换 | Container hardening practices | text/147-fm-container-hardening-practices.txt:171(搜「HEALTHCHECK」) · text/147-fm-container-hardening-practices.txt:188(搜「replace it」) |
| 组合基线 | Container hardening practices | text/147-fm-container-hardening-practices.txt:191(搜「Putting it all together」) · text/147-fm-container-hardening-practices.txt:200(搜「--read-only」) · text/147-fm-container-hardening-practices.txt:213(搜「strong baseline」) |
| 加固代价表 | Container hardening practices | text/147-fm-container-hardening-practices.txt:215(搜「Trade-offs」) · text/148-fm-secrets-management.txt:1(搜「Potential Downsides」) |
| secrets 挂载 | Secrets management | text/149-fm-runtime-security-tools.txt:7(搜「/run/secrets/db_password」) · text/149-fm-runtime-security-tools.txt:5(搜「docker compose up」) |
| 运行时 Falco | Runtime security tools | text/150-fm-summary.txt:1(搜「stale」) · text/141-fm-observability-and-security-monitoring.txt:31(搜「Falco」) |
-
出处:「Chapter 13: Securing Containers」第 1–16 段(
text/144-ch13-chapter-13-securing-containers.txt:4,搜「attack surface」)与「Supply chain security」的安装步骤(text/145-fm-supply-chain-security.txt:1,搜「Installing Trivy」)。 ↩↩ -
出处:「Supply chain security」第 1–20 段(
text/145-fm-supply-chain-security.txt:5,搜「official binaries」;:3,搜「WSL2」)。 ↩ -
出处:「Image vulnerability scanning and content trust」第 1–10 段(
text/146-fm-image-vulnerability-scanning-and-content-trust.txt:2,搜「floating tag」;:3,搜「cosign generate-key-pair」)。 ↩↩ -
出处:「Container hardening practices」第 1–11 段(签名执行段因转码顺序位于本文件开头:
text/147-fm-container-hardening-practices.txt:1,搜「signature verification」;:3,搜「Connaisseur」;:8,搜「defense-in-depth」;:11,搜「cannot enter production」)。 ↩↩↩ -
出处:「Container hardening practices」第 13–26 段(
text/147-fm-container-hardening-practices.txt:17,搜「tightening」;:18,搜「attack surface」)。 ↩ -
出处:「Container hardening practices」第 28–86 段(
text/147-fm-container-hardening-practices.txt:29,搜「run as root」;:40,搜「groupadd -r」;:42,搜「USER appuser」;:58,搜「cap-drop ALL」;:67,搜「don't include it」;:69,搜「escalate privileges」;:83,搜「alternative」)。 ↩↩↩↩ -
出处:「Container hardening practices」第 88–127 段(
text/147-fm-container-hardening-practices.txt:99,搜「--read-only」;:105,搜「writable volumes」;:113,搜「minimal images」;:118,搜「distroless」;:121,搜「multi-stage」;:126,搜「intermediate layers」)。 ↩↩ -
出处:「Container hardening practices」第 129–156 段(
text/147-fm-container-hardening-practices.txt:135,搜「seccomp filters」;:137,搜「AppArmor and SELinux」;:140,搜「User namespaces」;:143,搜「privileged mode」;:146,搜「--icc=false」;:152,搜「seccomp=default.json」)。 ↩↩ -
出处:「Container hardening practices」第 158–166 段(
text/147-fm-container-hardening-practices.txt:162,搜「--memory」;:166,搜「denial-of-service」)。 ↩↩ -
出处:「Container hardening practices」第 168–189 段(
text/147-fm-container-hardening-practices.txt:172,搜「HEALTHCHECK」;:177,搜「retries=3」;:188,搜「replace it」)。 ↩↩ -
出处:「Container hardening practices」第 191–213 段(
text/147-fm-container-hardening-practices.txt:196,搜「hardening flags」;:200,搜「--read-only」;:213,搜「strong baseline」)。 ↩↩ -
出处:「Container hardening practices」第 215 段起与「Secrets management」开头的代价表(
text/147-fm-container-hardening-practices.txt:216,搜「every restriction」;text/148-fm-secrets-management.txt:1,搜「Potential Downsides」)。 ↩↩↩ -
出处:「Secrets management」与「Runtime security tools」的演示(因转码顺序位于文件 149:
text/149-fm-runtime-security-tools.txt:5,搜「docker compose up」;:5,搜「/run/secrets/db_password」)。 ↩↩ -
出处:「Runtime security tools」(
text/150-fm-summary.txt:1,搜「stale」)与「Observability and security monitoring」的运行时监控段(text/141-fm-observability-and-security-monitoring.txt:31,搜「Falco」)。 ↩↩