amend gitignore
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
# 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 <uid> -m <rootfs路径> -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
|
||||
Reference in New Issue
Block a user