生产化、安全与可观测性:从概念到可验证实践
0. 元信息
- 主题路径:
docs/topics/docker-basics/subtopics/production-security-observability/README.md - 主分类:工程技术
- 辅助分类:安全与可靠性
- 适合对象:完成 Linux 基础并按父主题路线学习的开发者
- 建议周期:5~8 天,每天 1.5~2 小时
- 前置知识:image-build-and-distribution, container-runtime-network-storage, compose-multi-container
- 最终目标:能独立完成并解释 multi-stage、cache、SBOM、scan、rootless、capability、seccomp、日志指标与恢复 的实验,留下配置、命令和输出证据
1. 学习路线
概念与对象 → 最小正常实验 → inspect/日志验证 → 边界与失败实验 → 自动化配置 → 交付说明
2. 阶段周数分配
精简子主题不固定周数。按概念、正常路径、失败路径、综合实验四段推进,共 5~8 天。
3. 九阶段表
| 阶段 | 核心知识 | 实践产出 | 可观察学会标准 |
|---|---|---|---|
| 1 | 术语与对象边界 | 对象关系图 | 不混淆声明、制品与运行状态 |
| 2 | 默认行为 | 最小正常实验 | 能从空环境重现 |
| 3 | 配置语法 | 可版本化配置 | config/inspect 与预期一致 |
| 4 | 生命周期 | 状态变化记录 | 能解释 create/start/stop/remove 影响 |
| 5 | 隔离与依赖 | 拓扑或 mount 图 | 能指出宿主与容器边界 |
| 6 | 错误路径 | 至少四类故障 | 结论指向日志、事件或状态证据 |
| 7 | 安全与资源 | 最小权限配置 | 默认权限和 limit 有解释 |
| 8 | 可重复性 | 清理后重建记录 | 第三方按 README 可重现 |
| 9 | 综合实验 | 可运行交付物 | 能演示、排错、恢复与清理 |
4. 第一周任务
精简子主题省略逐日表。每天只引入一个变量;先跑正常路径,再做四类失败实验。
5. 阶段通用验收
采用父主题 §5;本页额外要求保存版本、完整配置、关键输出和清理命令。
6. 最终验收
完成一份可运行配置、至少四个失败案例、一次清理后重建,并用 10 分钟解释关键边界。
7. 综合项目
把本页产出合入父主题 Compose Web 应用。单独交付时,提供最小 demo、README、测试记录与 notes/retrospective.md。
本主题贡献
生产化阶段不是把 image 跑起来就结束,而是 SBOM + scan + cosign + seccomp + rootless + observability 一起守住供应链与运行时。本子主题专门写清”扫描发现 CVE 怎么办”、“seccomp 怎么按需收紧”、“日志/指标/trace 怎么串联”三件事的最小可行版本,并给出 multi-stage 瘦身后再加固的标准化顺序。
3 职责
- 把多工具漏洞扫描(trivy + grype + docker scout)做对比,输出 fixed version 与例外清单,CI 门禁按 severity 分级拦截 HIGH/CRITICAL。
- 把 SBOM(SPDX / CycloneDX)与 cosign sign / verify-attestation / admission controller 串成不可绕过链。
- 用 rootless +
--cap-drop=ALL+ seccomp profile +--read-only+ resource limit 做运行时最小权限,并接日志/指标/事件三向观测。
4 交付物
- 一份 trivy / grype / docker scout 对比表(同一 image 的 CVE 数、severity、fixed version),含 SBOM(
docker sbom+syft)输出与差异分析。 - 一份 cosign 签名 + 验签脚本(
cosign sign+cosign verify+cosign attach sbom),含验签失败的反例(digest 被改、key 不匹配)。 - 一份 seccomp profile JSON(最小 syscall 集合 +
SCMP_ACT_ERRNO默认拒绝),附违规 syscall 触发记录与--security-opt seccomp=验证。 - 一份最小权限
docker run模板(rootless + read-only + cap-drop + seccomp + log-driver json-file + OCI labels),含 multi-stage 瘦身后再加固的标准化顺序。
3 指标
- HIGH / CRITICAL CVE 修复周期 < 7 天(从 scan 发现到 image rebuild 推送)。
- 容器逃逸面缩减比 = 默认 capability 数 − 现 capability 数(cap-drop + seccomp 前后;目标是 14 → 1)。
- 日志/指标/trace 同 traceid 命中率 100%(Grafana 三向跳转 demo,含 OTel Collector 串联)。
Docker Docs 作主线;OCI 文档用于契约;Moby、BuildKit、containerd、runc 源码只在需要确认实现时查。复制前核对当前 LICENSE。
8. 推荐开源资料
Docker Docs 作主线;OCI 文档用于契约;Moby、BuildKit、containerd、runc 源码只在需要确认实现时查。复制前核对当前 LICENSE。
9. 学习资料汇聚(v0.3 自包含)
9.1 背景与动机
本子主题处理:覆盖多阶段瘦身、缓存、扫描、rootless、最小权限、日志指标和故障处理。。Docker 的易用 CLI 会隐藏多层状态。我们通过最小实验、inspect 和失败注入把对象关系变成可观察事实。
9.2 概念地图
flowchart LR
Spec[声明 / Spec] --> Engine[Docker Engine / BuildKit]
Engine --> Artifact[image / config / state]
Artifact --> Runtime[container runtime]
Runtime --> Evidence[inspect / logs / events / metrics]
Failure[故障注入] --> Runtime
Evidence --> Fix[修改与验证]
本页核心概念:multi-stage、cache、SBOM、scan、rootless、capability、seccomp、日志指标与恢复。声明经过 engine 产生制品或运行状态,所有判断回到 evidence。
9.3 基础知识讲解
9.3.1 论文 / 规范
| 资料 | 用法 |
|---|---|
| OCI Image Format Specification | 核对 manifest、config 与 layer digest |
| OCI Runtime Specification | 核对 bundle、config.json 与 lifecycle |
| NIST SP 800-190 Application Container Security Guide | 建立镜像、registry、orchestrator、host 风险模型 |
9.3.2 书
| 资料 | 用法 |
|---|---|
| Brendan Burns, Designing Distributed Systems | 学 sidecar、ambassador、adapter 等容器协作模式 |
| Liz Rice, Container Security | 结合 namespace、capability、seccomp 理解隔离边界 |
| Nigel Poulton, Docker Deep Dive | 补 Docker Engine、image、network、volume 主线 |
9.3.3 博客 / 文档
| 资料 | 用法 |
|---|---|
| Docker 官方文档 | 命令、Dockerfile、Compose、BuildKit 主线 |
| OWASP Docker Security Cheat Sheet | 配置安全检查表;并延伸阅读 OWASP Docker Top 10 |
| Kubernetes The Hard Way | 由 Kelsey Hightower 维护,用手工部署理解容器编排边界 |
| Aqua Trivy | 扫 image、filesystem、SBOM 与 misconfiguration |
| Snyk Container | 对照另一套 image dependency 风险视图 |
9.3.4 人物
| 人物 | 关注点 |
|---|---|
| Solomon Hykes | Docker 项目起点与开发者体验 |
| Kelsey Hightower | Kubernetes 教学、The Hard Way 与运维实践 |
| Liz Rice | 容器运行时、安全、eBPF 与隔离边界 |
| Brendan Burns | 容器编排与分布式系统模式 |
9.3.5 方法
| 方法 | 动作 |
|---|---|
| Inspect-first | 用 docker inspect、history、diff 看真实状态,不猜 |
| Immutable build | image 构建一次,按 digest 提升到各环境 |
| Least privilege | 非 root、drop capabilities、只读文件系统、限制资源 |
| Reproducible build | 锁 base digest、依赖版本与 build context,保留 provenance |
| Failure injection | 主动停服务、断网络、损坏健康检查,观察恢复和告警 |
| Evidence-based sizing | 用 metrics 决定 CPU/memory limit,不复制默认值 |
9.4 经典问题与经典案例
| # | 问题 | 最简答案 |
|---|---|---|
| 1 | 非 root 为何仍不够? | 仍需 drop capability、seccomp、只读 rootfs 与资源限制。 |
| 2 | rootless 解决所有隔离问题吗? | 降低 daemon/container root 风险,不消除 kernel 漏洞与配置风险。 |
| 3 | 扫描结果如何处理? | 按 fixed version、可利用性和时限决定升级或例外。 |
| 4 | 容器重启为何掩盖故障? | restart policy 只恢复进程,不解释根因。 |
| 5 | 日志、指标、trace 怎么关联? | 统一 timestamp、service/container id 与 request/trace id。 |
| 6 | 怎样安全 prune? | 先列对象、确认 label/owner/backup,再按对象类型清理。 |
9.4.1 实战片段:扫描、签名、SBOM 与最小权限
# trivy image --severity HIGH,CRITICAL ghcr.io/acme/app:v1
ghcr.io/acme/app:v1 (alpine 3.20.3)
=============================
Total: 3 (HIGH: 2, CRITICAL: 1)
┌────────────┬─────────────────┬──────────┬───────────────────┬───────────────┐
│ Library │ Vulnerability │ Severity │ Installed Ver │ Fixed Version │
├────────────┼─────────────────┼──────────┼───────────────────┼───────────────┤
│ openssl │ CVE-2024-xxxxx │ CRITICAL │ 3.1.4-r2 │ 3.1.5-r0 │
│ musl │ CVE-2024-yyyyy │ HIGH │ 1.2.4-r2 │ 1.2.5-r0 │
│ libxml2 │ CVE-2024-zzzzz │ HIGH │ 2.12.7-r0 │ 2.12.9-r0 │
└────────────┴─────────────────┴──────────┴───────────────────┴───────────────┘
# 1. 多工具扫描与对比
trivy image --format json -o trivy.json ghcr.io/acme/app:v1
grype -o json ghcr.io/acme/app:v1 > grype.json
docker scout cves ghcr.io/acme/app:v1
# 2. SBOM(SPDX / CycloneDX)
docker sbom --format spdx-json ghcr.io/acme/app:v1 > app.spdx.json
syft ghcr.io/acme/app:v1 -o cyclonedx-json > app.cdx.json
# 3. 签名 + 证明 + 验签
cosign generate-key-pair
cosign sign --key cosign.key ghcr.io/acme/app:v1
cosign sign --key cosign.key 'ghcr.io/acme/app@sha256:<digest>'
cosign verify --key cosign.pub ghcr.io/acme/app:v1
cosign attach sbom --sbom app.spdx.json ghcr.io/acme/app:v1
cosign verify-attestation --type sbom --key cosign.pub ghcr.io/acme/app:v1
# 4. 运行时最小权限 + 观测
docker run -d --name api \
--read-only --tmpfs /tmp:size=32m \
--cap-drop=ALL --cap-add=NET_BIND_SERVICE \
--security-opt no-new-privileges:true \
--security-opt seccomp=seccomp-profiles/api.json \
--pids-limit=200 --memory=512m --cpus=1.0 \
--log-driver=json-file --log-opt max-size=10m --log-opt max-file=5 \
--label org.opencontainers.image.source=https://github.com/acme/app \
ghcr.io/acme/app:v1
docker logs --tail 100 -f api
docker stats api --no-stream
docker events --since 5m --filter container=api
# seccomp-profiles/api.json(最小子集示例,按需放宽)
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": ["SCMP_ARCH_X86_64", "SCMP_ARCH_AARCH64"],
"syscalls": [
{"names": ["read","write","openat","close","exit_group","futex","epoll_pwait","clock_gettime","mmap","mprotect","brk","rt_sigaction","prlimit64","getrandom","set_robust_list"], "action": "SCMP_ACT_ALLOW"}
]
}
9.5 学习难点
概念难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| 声明与状态 | 文件正确不代表运行状态正确 | 同时看配置渲染、inspect 和实际 I/O |
| 隔离边界 | UI 隐藏 namespace、mount、network | 画宿主、daemon、runtime、进程四层图 |
| 默认值 | 版本和平台会改变行为 | 记录版本,查官方 reference,显式写关键值 |
思维难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| 从错误文本找层级 | client、daemon、runtime、app 都能报错 | 先标错误产生者,再沿调用链检查 |
| 正常路径偏见 | 跑通一次容易误判稳定 | 端口、权限、资源、依赖各造一次故障 |
| 可变状态 | tag、container、volume 会随操作变化 | 每步记录对象 ID/digest 与前后状态 |
工程难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| 跨平台与权限 | kernel、filesystem、UID 行为不同 | 在目标平台跑验收,写明已知限制 |
| 清理与数据安全 | remove/prune 可能不可逆 | 先列对象与备份,再执行精确删除 |
| 可观测性 | 单一日志缺上下文 | 关联 inspect、events、stats、health 与应用指标 |
9.6 技术标准与接口
9.6.1 Entity
| 名称 | 发布组织 | 角色 | 状态 / 可访问性 |
|---|---|---|---|
| OCI Image Spec | Open Container Initiative | image manifest、config、layer 格式 | 开放标准,Apache-2.0 |
| OCI Runtime Spec | Open Container Initiative | bundle 与容器运行生命周期 | 开放标准,Apache-2.0 |
| containerd | CNCF | image、snapshot、container、task 管理 | 活跃,Apache-2.0 |
| runc | Open Container Initiative | OCI runtime reference implementation | 活跃,Apache-2.0 |
| CNI | CNCF | 容器网络插件接口 | 活跃,Apache-2.0 |
| CSI | CNCF | 容器编排系统存储接口 | 活跃,Apache-2.0 |
9.6.2 Scope
OCI 定义 image 与 runtime 契约,不定义完整编排。containerd 管高层生命周期,runc 执行 OCI bundle。CNI、CSI 面向编排系统;Docker bridge、volume driver 有自己的实现接口。Docker Compose 处理单机或 context 上的多服务应用,不替代 Kubernetes 的集群调度。
9.6.3 Structure
必须掌握 image manifest/config/layer、content digest、OCI bundle、config.json、namespace、cgroup、capability、seccomp、network namespace、mount、snapshotter。常用接口是 Docker CLI/API、Dockerfile、Compose Specification、registry HTTP API。
9.6.4 Ecosystem
Docker Engine 由 daemon、containerd、runc 等组成。替代或邻接实现有 Podman、Buildah、BuildKit、nerdctl、CRI-O、Kubernetes。扩展点包括 BuildKit frontend/cache exporter、network/volume/logging plugin、CNI 与 CSI driver。Compose 文件规范与具体 engine 支持范围要分开核对。
9.6.5 Depth Tiers
| 层级 | 可观察能力 |
|---|---|
| L0 | 知道 image、container、registry、volume、network、Compose 的职责 |
| L1 | 看懂 Dockerfile、docker run 和 compose.yaml 示例 |
| L2 | 能正确 build、run、push、备份、编排并处理常见参数错误 |
| L3 | 能解释 layer、namespace/cgroup、网络存储路径并用日志、stats、inspect 排错 |
| L4 | 能设计 runtime、plugin、供应链策略或大规模编排平台 |
本计划目标是 L3。
9.6.6 Source
- Docker 官方文档:CLI、Dockerfile、BuildKit、Compose、rootless 与生产建议。
- Moby 项目仓库:Docker Engine 核心实现,Apache-2.0。
- containerd 仓库:runtime 管理实现,Apache-2.0。
- 引用版本快照日期:2026-07-30;实作前运行
docker version与docker compose version。
10. 常见误区
- 只复制命令,不理解对象状态;
- 以 tag 代替 digest;
- 默认 root;
- 把 secret 写进 image 或仓库;
- 用重启掩盖 readiness 和数据问题;
- 只测试正常路径;
- 不记录 Docker/Compose 版本;
- 不区分 Docker 行为、OCI 契约和 Linux kernel 能力;
- 看见报错就重建全部对象;
- 未备份就 remove volume 或 prune。
11. 所有知识点分类(统一规则)
- 编程语言;2. 数据结构与算法;3. 计算机基础;4. 工程技术;5. Web 与后端;6. 前端与客户端;7. 数据与人工智能;8. 项目与职业能力;9. 安全与可靠性。
本计划归属:工程技术 主 + 安全与可靠性 辅。