3. Docker 基础回顾:Dockerfile、镜像分层、容器生命周期、网络模式与数据卷
在深入可观测性租户隔离之前,必须夯实 Docker 核心基础。本章从 Dockerfile 构建、镜像分层机制、容器生命周期、网络模式 与 数据卷 五个维度展开,为后续的隔离策略与安全评估提供底层知识支撑。
3.1 Dockerfile 与镜像分层
Dockerfile 是定义镜像构建过程的声明式脚本,每一行指令对应一个只读层(Layer)。分层机制是镜像复用与缓存加速的核心。
3.1.1 典型 Dockerfile 结构
# 基础镜像层
FROM alpine:3.18
# 元数据层
LABEL maintainer="sre-team@example.com" \
version="1.0.0"
# 环境变量层
ENV APP_HOME=/opt/app \
LOG_LEVEL=info
# 工作目录层
WORKDIR $APP_HOME
# 依赖安装层
RUN apk add --no-cache python3 py3-pip
# 代码复制层
COPY ./app ./app
COPY ./requirements.txt .
# 依赖安装层(利用缓存)
RUN pip install --no-cache-dir -r requirements.txt
# 端口暴露层
EXPOSE 8080
# 启动命令层
CMD ["python3", "./app/main.py"]
3.1.2 镜像分层原理
| 层类型 | 特性 | 缓存条件 |
|---|---|---|
| 基础层(FROM) | 只读,从 Registry 拉取 | 镜像摘要不变即命中 |
| 指令层(RUN/COPY/ADD) | 只读,每层生成一个中间镜像 | 指令字符串与上下文未变 |
| 可写层(容器层) | 容器运行时创建,销毁即丢失 | 不参与缓存 |
关键认知: 镜像层是只读的,容器启动时在顶部叠加一个可写层。所有写操作(日志、临时文件)都发生在可写层,这也是容器重启后数据丢失的根本原因。
3.2 容器生命周期
容器从创建到销毁经历明确的状态转换。理解生命周期是排查故障、设计健康检查与优雅关闭的基础。
3.2.1 状态转换图
| 状态 | 说明 | 常见触发命令 |
|---|---|---|
| created | 镜像已加载,文件系统就绪,未启动进程 | docker create |
| running | 主进程正在执行,可接受网络请求 | docker start / docker run |
| paused | 进程被 SIGSTOP 挂起,CPU 不分配 | docker pause |
| exited | 主进程终止(正常退出或崩溃) | docker stop / 进程退出 |
| dead | 容器已停止且资源未完全清理 | docker kill 强制终止 |
可观测性实践: 在容器退出前,通过
STOPSIGNAL 和 HEALTHCHECK 指令配合生命周期钩子,可以优雅地采集退出前的日志与指标,避免数据丢失。
3.3 网络模式
Docker 网络模式决定了容器间通信、端口映射与隔离边界。在租户隔离场景中,网络模式的选择直接影响安全域划分。
| 模式 | 隔离级别 | IP 分配 | 适用场景 |
|---|---|---|---|
| bridge(默认) | 容器间隔离,通过 docker0 桥接 | 172.17.0.0/16 子网 | 单机多容器通信 |
| host | 无隔离,共享宿主机网络栈 | 宿主机 IP | 高性能网络、监控 Agent |
| none | 完全隔离,无网络接口 | 无 | 离线计算、安全沙箱 |
| overlay | 跨主机容器通信,VXLAN 封装 | 自定义子网 | Swarm/K8s 集群 |
| macvlan | 容器拥有独立 MAC 地址 | 物理网络子网 | 遗留应用、网络策略绑定 |
安全评估要点: 在租户隔离架构中,禁止使用
--network=host 模式,因为它会绕过 iptables 规则与网络命名空间隔离。推荐使用自定义 bridge 网络 + 子网划分实现租户级网络隔离。
3.4 数据卷(Volume)
数据卷是 Docker 持久化数据的标准机制,独立于容器生命周期。在可观测性场景中,日志、指标与 Trace 数据的持久化依赖 Volume 的正确配置。
3.4.1 三种挂载方式对比
| 类型 | 管理方式 | 性能 | 隔离性 | 推荐场景 |
|---|---|---|---|---|
| Volume | Docker 管理(/var/lib/docker/volumes/) |
高 | 好 | 数据库、日志持久化 |
| Bind Mount | 用户指定宿主机路径 | 高 | 差(依赖宿主机路径) | 开发调试、配置文件注入 |
| tmpfs | 内存中,不写入磁盘 | 极高 | 好 | 敏感数据、临时缓存 |
3.4.2 可观测性数据卷实践
# 创建专用卷用于日志采集
docker volume create --name observability-logs \
--label tenant=team-a \
--label environment=production
# 挂载到容器
docker run -d \
--name app-service \
--mount source=observability-logs,target=/var/log/app \
--mount type=tmpfs,target=/tmp/cache,tmpfs-size=100m \
my-app:1.0.0
# 查看卷元数据(用于审计)
docker volume inspect observability-logs --format '{{.Labels}}'
租户隔离建议: 为每个租户创建独立的 Volume,并附加
tenant 与 environment 标签。在可观测性管道中,通过 Volume 标签路由日志与指标到对应的租户存储桶,实现数据面隔离。
3.5 本章小结
- Dockerfile 的每一行指令生成一个只读层,合理排序可最大化缓存命中率。
- 镜像分层 是镜像复用与增量推送的基础,容器可写层不持久化。
- 容器生命周期 包含 created → running → paused → exited → dead 五个状态,健康检查应覆盖 running 与 paused 状态。
- 网络模式 中自定义 bridge 与 overlay 是租户隔离的首选,host 模式禁止用于多租户环境。
- 数据卷 通过 Volume 标签实现租户级数据隔离,tmpfs 适用于临时敏感数据。