master
- include/container.h: document struct fields and constants - src/main.c: explain argument parsing, clone flow, parent/child roles - src/mount.c: describe 6-step mount isolation process - src/cgroup.c: explain cgroup data structures and resource setup/cleanup - src/capabilities.c: document capability drop (bounding + inheritable) - src/seccomp.c: explain each seccomp rule's security purpose - src/userns.c: describe parent-child sync and uid_map/gid_map format - src/hostname.c: document tarot card random naming scheme
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
依赖
# Alibaba Cloud Linux / RHEL
dnf install -y libseccomp-devel libcap-devel
# Ubuntu / Debian
apt install -y libseccomp-dev libcap-dev
编译
make
清理:
make clean
用法
./container-from-scratch -u <uid> -m <rootfs路径> -c <命令>
| 参数 | 含义 |
|---|---|
-m |
容器根文件系统目录(rootfs) |
-u |
容器内进程的 UID |
-c |
要执行的命令(必须放最后) |
快速开始
1. 创建 rootfs
mkdir -p rootfs
dnf install -y --installroot=$(pwd)/rootfs --releasever=3 bash coreutils procps-ng iproute hostname
2. 准备 /dev/null
rm -f rootfs/dev/null
mknod -m 666 rootfs/dev/null c 1 3
3. 运行容器
# 交互式 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
Languages
C
94.5%
Shell
4.1%
Makefile
1.4%