Docker 容器化:从镜像到 Compose 与多容器编排
0. 元信息
- 主题路径:
docs/topics/docker-basics/README.md
- 主分类:工程技术
- 辅助分类:安全与可靠性
- 适合对象:会 Linux shell、进程、文件权限和基础网络的开发者
- 建议周期:4~6 周,每周 8~12 小时
- 前置知识:
linux-dev-env
- 最终目标:能构建可重复、可扫描、非 root 的 image,用 Compose 部署并排查前后端、数据库、反向代理应用
1. 学习路线
image/container 基础 → Dockerfile 与 layer → registry 与 buildx
→ run 生命周期与资源限制 → network 与 volume
→ Compose 服务图 → 多阶段构建与缓存 → 安全、观测与故障处理
2. 阶段周数分配
| 阶段 | 4 周方案 | 6 周方案 | 备注 |
|---|
| 1. 基础与 CLI | 0.4 | 0.5 | image、container、inspect |
| 2. Dockerfile | 0.5 | 0.75 | layer、context、cache |
| 3. 分发与多平台 | 0.35 | 0.5 | registry、save/load、buildx |
| 4. 运行与资源 | 0.4 | 0.6 | namespace、cgroup、signal |
| 5. 网络与存储 | 0.5 | 0.75 | bridge、DNS、volume、backup |
| 6. Compose | 0.5 | 0.75 | 服务图、healthcheck、profiles |
| 7. 生产构建 | 0.45 | 0.75 | multi-stage、cache、SBOM、scan |
| 8. 安全与观测 | 0.45 | 0.75 | rootless、capability、logs、stats |
| 9. 综合项目 | 0.45 | 0.65 | 故障注入与验收 |
3. 九阶段表
| 阶段 | 核心知识 | 实践产出 | 可观察学会标准 |
|---|
| 1 | client/daemon、image/container、tag/digest、lifecycle | nginx 容器实验 | 能用 ps/inspect/logs/exec/rm 说明状态,不混淆 image 和 container |
| 2 | Dockerfile、context、.dockerignore、layer、cache | 可重复应用 image | 能解释 COPY 顺序如何影响 cache,PID 1 用 exec form |
| 3 | registry、push/pull、save/load、buildx | 双平台构建记录 | 能解释 tag 可变、digest 不变;会离线导入导出 |
| 4 | namespace、cgroup、signal、limit、restart、live-restore | 资源和退出实验 | 能证明 CPU/memory 限制生效,正确处理 SIGTERM |
| 5 | bridge、端口、DNS、volume、bind mount、driver | 数据库备份恢复 | 能区分容器端口与宿主端口,删除容器后恢复数据 |
| 6 | Compose service/network/volume、depends_on、healthcheck | 三服务 compose.yaml | 能用服务名通信,能解释启动顺序不等于就绪 |
| 7 | multi-stage、BuildKit cache mount、瘦身、SBOM、scan | 生产 Dockerfile | 最终 image 无编译器,漏洞结果有处置说明 |
| 8 | rootless、user、capability、seccomp、read-only、logs/metrics | hardening 与观测清单 | 容器非 root,权限受限,故障能由 logs/events/stats 定位 |
| 9 | 版本锁定、配置、secret、备份、回滚、prune | 完整 Web 应用 | 新机器可按 README 部署、升级、回滚与清理 |
4. 第一周任务
Day 1 运行约定:使用 Docker Engine 与 Compose v2;记录 docker version、docker info、docker compose version。命令在测试环境运行,删除或 prune 前先列对象。
| 日 | 任务 | 当天交付 |
|---|
| Day 1 | docker run --name web -d -p 8080:80 nginx:alpine,练 ps/logs/inspect/exec/stop/rm | 命令和状态变化表 |
| Day 2 | 写静态站点 Dockerfile 与 .dockerignore | image、build log、history |
| Day 3 | 改依赖与源码顺序,比较缓存命中 | 两次 build 时间和原因 |
| Day 4 | bridge network 上启动 app/db,验证服务名 DNS | 拓扑与连接证据 |
| Day 5 | volume 保存数据,完成 backup/restore | 备份包和恢复记录 |
| Day 6 | 写 compose.yaml,加入 healthcheck | docker compose ps 与日志 |
| Day 7 | 步骤 A:docker compose -f compose.yaml up -d 跑通最小应用;步骤 B:测试端口冲突、健康检查失败、数据库不可达、volume 权限错误 | 正常证据、四类异常与处理记录 |
5. 阶段通用验收
- 从空环境重做核心命令;2. 解释对象、生命周期与隔离边界;3. 保存配置、版本与原始输出;4. 测试失败路径;5. 每阶段至少三组实验;6. 记录 image size、build time、CPU/memory;7. 修改配置后用同一检查验证。
6. 最终验收
- 独立写 multi-stage Dockerfile、
.dockerignore、healthcheck 与 compose.yaml;
- 完成至少 18 个实验,其中网络/存储、安全/故障各不少于 3 个;
- 会运行
docker save app:v1 | gzip > app.tgz 并恢复;
- 会运行
docker buildx build --platform linux/amd64,linux/arm64 -t app:v1,需要发布时补 --push;
- 完成综合项目并用 15 分钟解释 image 到 runtime 的链路。
7. 综合项目
首选:用 Docker Compose 部署一个含前后端 + 数据库 + 反向代理的完整 Web 应用。
必须包含独立 network、持久 volume、healthcheck、环境变量示例、非 root 应用 image、multi-stage build、资源限制、日志查看、数据库备份恢复、漏洞扫描、升级回滚和清理命令。敏感值不提交进 image 或仓库。
备选:写一个支持多阶段构建、镜像扫描、根用户禁用的生产级 Dockerfile。
项目交付需求说明、架构图、Dockerfile、compose.yaml、测试、运行说明、故障记录和 notes/retrospective.md。
8. 推荐开源资料
| 角色 | 资料 | 许可证 / 可访问性 | 用法 |
|---|
| 主线 | Docker Docs | 公开文档 | 跟 guides 实作,CLI 以 reference 为准 |
| 构建 | BuildKit | Apache-2.0 | cache、secret mount、multi-platform |
| 引擎 | Moby | Apache-2.0 | 查 daemon 与网络存储实现 |
| runtime | containerd、runc | Apache-2.0 | 看 OCI 生命周期 |
| 安全 | Trivy | Apache-2.0 | image、SBOM、misconfiguration 扫描 |
| 编排模式 | Designing Distributed Systems | 书籍 | 对照 sidecar 等协作模式 |
9. 学习资料汇聚(v0.3 自包含)
9.1 背景与动机
容器把应用进程、文件系统视图、网络与资源控制装进可分发单元。它共享宿主 kernel,不是轻量 VM。Docker 把 Linux namespace、cgroup、union filesystem、OCI image、registry 与易用 CLI 组合成开发交付流程。今天学 Docker,重点是可重复构建、隔离边界、供应链和运行证据。
9.2 概念地图
flowchart LR
Dockerfile --> BuildKit --> Image --> Registry
Image --> Container
Registry --> Image
Container --> Namespace
Container --> Cgroup
Container --> Network
Container --> Volume
Compose --> Container
Compose --> Network
Compose --> Volume
Scan[SBOM / Trivy / Snyk] --> Image
Observe[logs / events / stats] --> Container
Image 是只读 layer 与 config。container 在 image 上加 writable layer 并由 runtime 启动进程。Compose 声明一组 service、network、volume。扫描看制品风险,观测工具看运行状态。
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 博客 / 文档
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,不复制默认值 |
还要能执行这些真实路径:docker scan app:v1 在当前安装提供该命令时运行;新环境更常用 docker scout cves app:v1、trivy image app:v1 或 Snyk Container。离线分发用 docker save app:v1 | gzip > app.tgz 与 gunzip -c app.tgz | docker load。
9.4 经典问题与经典案例
| 问题 | 为什么重要 | 最简答案 |
|---|
| 容器退出后数据没了 | writable layer 随容器生命周期变化 | 数据放 named volume 或外部服务并验证备份 |
localhost 连不到另一服务 | localhost 指当前容器 | 同 network 用 Compose service name |
| image 越构建越大 | layer 删除不等于抹掉旧 layer | 同层清理或 multi-stage,只复制运行产物 |
depends_on 后 app 仍启动失败 | 启动顺序不表示依赖已就绪 | healthcheck、重试与幂等迁移 |
| bind mount 后文件消失 | mount 覆盖容器内原路径 | 检查 source/target、权限与宿主目录内容 |
| build cache 不命中 | context、指令顺序或参数变化 | 稳定依赖层放前,源码层放后,检查 BuildKit 输出 |
| multi-platform image 跑不了 | builder、emulation、base image 或 push 方式不匹配 | 检查 buildx builder、platform manifest 与 registry |
| 扫描有 CVE 怎么办 | 有 CVE 不等于可利用,也不能忽略 | 看 fixed version、reachable、severity、base 更新与例外期限 |
| rootless 后端口/目录失败 | uid 映射和特权端口不同 | 检查 subuid/subgid、目录 owner 与 rootless 限制 |
| 日志很多仍找不到故障 | stdout 只有一层证据 | 关联 events、inspect、stats、health、应用指标与 trace |
9.4.1 实战片段:多阶段 Dockerfile 与 .dockerignore
# syntax=docker/dockerfile:1.7
# 阶段 1:构建
FROM golang:1.25-alpine AS build
WORKDIR /src
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go mod download
COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/app .
# 阶段 2:运行时
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /out/app /app
USER nonroot:nonroot
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD ["/app", "-health"]
ENTRYPOINT ["/app"]
# .dockerignore
.git
.idea
.vscode
node_modules
dist
build
*.log
.env
.env.*
notes/
# 构建、扫描、签名、SBOM、运行
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag ghcr.io/acme/app:v1 \
--label org.opencontainers.image.revision=$(git rev-parse HEAD) \
--push .
docker compose -f deploy/compose.yaml --env-file deploy/.env up -d
docker compose ps
docker compose logs --tail 100 -f api
# 镜像扫描与 SBOM
trivy image --severity HIGH,CRITICAL ghcr.io/acme/app:v1
grype ghcr.io/acme/app:v1
docker sbom ghcr.io/acme/app:v1 > app.spdx.json
# 签名与验签
cosign sign --key cosign.key ghcr.io/acme/app:v1
cosign verify --key cosign.pub ghcr.io/acme/app:v1
# 容量与清理
docker system df
docker system prune --filter "until=72h"
9.5 学习难点
概念难点
| 难点 | 为什么会卡 | 突破路径 |
|---|
| image 与 container | 常把模板和实例混为一谈 | 用 inspect 比较 image config、container state、mount |
| layer 与 union mount | 删除文件仍可能占 image 空间 | 用 docker history 和 dive 查看每层变化 |
| 容器隔离边界 | 误以为共享 kernel 等于 VM 隔离 | 对照 namespace、cgroup、capability 与 seccomp |
思维难点
| 难点 | 为什么会卡 | 突破路径 |
|---|
| 声明配置与运行状态 | Dockerfile/Compose 不等于当前容器状态 | 每次用 config、inspect、ps 三方核对 |
| 可变 tag 与不可变 digest | latest 看起来像版本 | 部署记录 digest,tag 只作人类标签 |
| 就绪与启动 | 进程已启动不表示可服务 | healthcheck 加应用重试,制造慢启动验证 |
工程难点
| 难点 | 为什么会卡 | 突破路径 |
|---|
| 缓存与跨平台 | builder、cache backend、QEMU、registry 交织 | 从单平台基线开始,再加 cache export 和第二平台 |
| 网络与权限 | 宿主、防火墙、UID、SELinux/AppArmor 都可能介入 | 记录宿主环境,从 inspect 到 namespace 分层检查 |
| 供应链与运行安全 | base、依赖、secret、runtime 权限跨多个阶段 | 生成 SBOM、扫描、签名/证明、最小权限并设更新时间 |
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. 常见误区
- 把 container 当 VM;
- 所有 image 都打
latest;
- 用
docker commit 代替 Dockerfile;
- 把 secret 写进 ENV、ARG 或 layer;
- 默认用 root 和全部 capabilities;
- 用 host network 逃避网络设计;
- 把 bind mount 和 named volume 混用却不写备份策略;
- 依赖
depends_on 代替 readiness;
- Dockerfile 一行一层,不考虑 cache 与 image size;
- 只看漏洞数量,不看修复版本和可利用路径;
- 线上随手
docker system prune -a --volumes;
- 只收日志,不收 health、events、资源和应用指标。
11. 所有知识点分类(统一规则)
- 编程语言;2. 数据结构与算法;3. 计算机基础;4. 工程技术;5. Web 与后端;6. 前端与客户端;7. 数据与人工智能;8. 项目与职业能力;9. 安全与可靠性。
本计划归属:工程技术 主 + 安全与可靠性 辅。