# Container From Scratch 用纯 C 从零实现一个简易容器运行时,演示 Linux 容器核心原理。 ## 功能 - **Namespace 隔离** — PID、UTS、NET、Mount、IPC、Cgroup、User - **Cgroup 资源限制** — 内存 1GB、CPU shares、最大 64 进程 - **Capability 权限收窄** — drop 20 个危险 capability - **Seccomp 系统调用过滤** — 禁止 ptrace、keyctl 等危险 syscall ## 依赖 ```bash # Alibaba Cloud Linux / RHEL dnf install -y libseccomp-devel libcap-devel # Ubuntu / Debian apt install -y libseccomp-dev libcap-dev ``` ## 编译 ```bash make ``` 清理: ```bash make clean ``` ## 用法 ``` ./container-from-scratch -u -m -c <命令> ``` | 参数 | 含义 | |------|------| | `-m` | 容器根文件系统目录(rootfs) | | `-u` | 容器内进程的 UID | | `-c` | 要执行的命令(必须放最后) | ## 快速开始 ### 1. 创建 rootfs ```bash mkdir -p rootfs dnf install -y --installroot=$(pwd)/rootfs --releasever=3 bash coreutils procps-ng iproute hostname ``` ### 2. 准备 /dev/null ```bash rm -f rootfs/dev/null mknod -m 666 rootfs/dev/null c 1 3 ``` ### 3. 运行容器 ```bash # 交互式 shell ./container-from-scratch -u 0 -m ./rootfs -c /bin/sh # 运行测试脚本 ./container-from-scratch -u 0 -m ./rootfs -c /test-container.sh ``` ## 项目结构 ``` container-from-scratch/ ├── include/ │ ├── container.h # 核心定义:child_config 结构体、系统头文件、常量 │ ├── mount.h # mounts() — 文件系统隔离 │ ├── cgroup.h # resources()、free_resources() — 资源限制 │ ├── capabilities.h # capabilities() — 权限收窄 │ ├── container_seccomp.h # syscalls() — 系统调用过滤 │ ├── userns.h # userns()、handle_child_uid_map() — 用户命名空间 │ └── hostname.h # choose_hostname() — 随机主机名 ├── src/ │ ├── main.c # 主流程:参数解析、clone、waitpid │ ├── mount.c # pivot_root、挂载 /proc、/dev │ ├── cgroup.c # cgroup 目录创建与清理 │ ├── capabilities.c # prctl + cap_set_flag drop 权限 │ ├── seccomp.c # seccomp 规则定义与加载 │ ├── userns.c # user namespace + UID/GID 映射 │ └── hostname.c # 塔罗牌随机名生成 ├── rootfs/ # 容器根文件系统 ├── test-container.sh # 容器环境测试脚本 ├── Makefile └── README.md ``` ## 工作原理 ``` main() ├── 解析参数(-m、-u、-c) ├── 检查内核版本(>= 4.7) ├── choose_hostname() → 生成随机主机名 ├── resources() → 创建 cgroup,写入资源限制 ├── clone() → 创建子进程(6 个 namespace flag) │ ├── [父进程] │ ├── handle_child_uid_map() → 写入 uid_map/gid_map │ └── waitpid() → 等待子进程退出 │ └── [子进程 — child()] ├── sethostname() → 设置容器主机名(UTS namespace) ├── mounts() → pivot_root + 挂载 /proc、/dev ├── userns() → 创建 user namespace + 切换 UID ├── capabilities() → drop 危险 capability ├── syscalls() → 加载 seccomp 过滤器 └── execve() → 执行目标命令 ``` ## 容器核心机制 | 机制 | 作用 | 类比 | |------|------|------| | **Namespace** | 隔离视野(进程、网络、文件系统...) | 每个房间有独立的门牌号和家具 | | **Cgroup** | 限制资源(内存、CPU、进程数) | 给每个房间限电限水 | | **Capabilities** | 细分 root 权限 | 老板权限拆成"能开保险柜"、"能进机房" | | **Seccomp** | 禁止危险系统调用 | 规定能用螺丝刀,不能用电钻 | 四者叠加 = 容器隔离。 ## License GPLv3