第一部分:不使用 Docker,仅通过 Linux 原生命令手工创建隔离环境。 第二部分:深入探索 Docker 和 OverlayFS 的分层存储机制。
下次课前 (一周)
编写一个 Shell 脚本 my_container.sh,实现以下功能:
#!/bin/bash
# my_container.sh — 手工容器脚本
# 用法: sudo ./my_container.sh <rootfs_dir> <command>
ROOTFS="$1"
COMMAND="$2"
要求:
unshare --mount + mount --bind 为进程创建独立的 mount namespace,或使用 chroot 切换到指定的 rootfsunshare --pid --fork 使进程看到独立的 PID 空间 (容器内 PID 从 1 开始)unshare --net 为进程分配独立的网络栈cgcreate/cgset 为进程设置:
# 创建 cgroup
sudo cgcreate -g cpu,memory:/mycontainer
# 设置 CPU 限制 (1 核心 = 100000 微秒/100000 微秒)
sudo cgset -r cpu.cfs_quota_us=100000 mycontainer
sudo cgset -r cpu.cfs_period_us=100000 mycontainer
# 设置内存限制
sudo cgset -r memory.limit_in_bytes=268435456 mycontainer # 256 MB
# 在隔离环境中运行程序
sudo cgexec -g cpu,memory:/mycontainer \
unshare --mount --pid --fork --net \
chroot /path/to/rootfs /bin/bash
# 准备最小 rootfs 的方法:
# 1. mkdir -p /tmp/mini-rootfs/{bin,lib,lib64,usr/lib,usr/lib64}
# 2. cp /bin/bash /tmp/mini-rootfs/bin/
# 3. 使用 ldd /bin/bash 找到依赖的 .so 文件并复制过去
在隔离环境中运行以下命令验证:
# 1. PID 隔离验证
echo "Container PID: $$" # 应该显示 1 或很小的数字
# 2. 文件系统隔离验证
ls / # 应该只看到 rootfs 中的文件
# 3. 网络隔离验证
ip addr # 应该只有 lo 接口
# 4. CPU 限制验证 (开另一个终端在宿主机运行)
# 在容器内: stress --cpu 2
# 在宿主机: top 观察 CPU 使用率,容器进程不应超过 1 核
# 5. 内存限制验证
# 在容器内: stress --vm 1 --vm-bytes 300M
# 应该触发 OOM Killer,进程被杀死
参考 cloud-native-dev §4,完成以下探索:
ubuntu:22.04, python:3.11),使用 docker history 查看其层结构。记录每一层的大小和用途。ubuntu:22.04 和 ubuntu:20.04 或 python:3.11),确认 docker system df -v 中共享层的存储仅计算一次。CACHED),哪些层被重建。解释缓存失效原理。docker inspect 找到某运行中容器的 UpperDir 和 LowerDir,进入 UpperDir 查看容器运行时产生的新文件和修改文件。删除容器后观察 UpperDir 的变化。在上述基础容器的基础上,实现以下增强功能:
docker commit 的效果参考 cloud-native-dev,使用 ip netns 创建两个网络隔离的 namespace,通过 veth pair 连接它们。验证网络隔离和连通性。
my_container.sh 脚本docker history 输出截图和分析| 维度 | 权重 | 要求 |
|---|---|---|
| 任务 1 (手工容器) | 35% | 至少实现 PID/Mount/Network 隔离 + CPU/内存限制之一 |
| 任务 2 (分层存储) | 35% | 完成所有 4 项探索并提交报告 |
| 代码与文档质量 | 15% | 脚本有清晰的注释、错误处理;报告有截图和分析 |
| 进阶任务 | 15% | 完成至少一项进阶功能 |
man unshare / man cgcreate / man cgset — Linux 手册