当前位置: 首页 > news >正文

如何用 100 行 Shell 代码实现一个 Docker?

严格来说,无法用 100 行 Shell 代码实现一个功能完整的 Docker 商业发行版,但我们可以编写一个约 100 行的脚本,调用 Linux 内核特性来模拟容器的核心隔离机制。以下方案适合用于理解原理而非生产环境。

先说结论:这类脚本本质是 Linux namespaces 和 cgroups 的封装,能跑通隔离流程,但缺乏镜像管理、网络插件和安全加固。

  • 适合:学习容器底层原理、验证内核隔离特性
  • 先看:脚本是否调用了 unshare、cgroup 相关接口
  • 建议:不要用于生产业务,仅作为实验环境

环境准备与依赖检查

在开始之前,确保你的 Linux 环境支持必要的内核特性。大多数现代发行版(Ubuntu 18.04+, CentOS 7+)默认开启,但需 root 权限。

# 检查是否支持 user namespace
cat /proc/user_namespaces# 检查 cgroup 版本
cat /sys/fs/cgroup/cgroup.controllers
# 如果有输出则是 cgroup v2,否则可能是 v1

准备根文件系统(Rootfs)

容器需要一个独立的文件系统。这里使用 BusyBox 作为最小化示例。

# 创建目录
mkdir -p ./rootfs
cd ./rootfs# 下载 BusyBox 静态编译版本(示例地址,请根据实际架构选择)
wget https://busybox.net/downloads/binaries/1.35.0-x86_64-linux-musl/busybox# 赋予执行权限并安装到当前目录
chmod +x busybox
./busybox `--install` -s .# 返回上一级
cd ..

核心脚本实现

以下脚本整合了命名空间隔离、根目录切换和基础清理逻辑。保存为 mini-docker.sh

#!/bin/bash
set -eROOTFS="./rootfs"
CONTAINER_NAME="test-container"# 1. 权限检查
if [ "$(id -u)" -ne 0 ]; thenecho "错误:需要 root 权限运行"exit 1
fi# 2. 检查 rootfs 是否存在
if [ ! -d "$ROOTFS" ]; thenecho "错误:未找到 $ROOTFS 目录,请先准备根文件系统"exit 1
fi# 3. 创建 Cgroup 目录 (以 v1 memory 为例)
CGROUP_PATH="/sys/fs/cgroup/memory/$CONTAINER_NAME"
if [ -d "/sys/fs/cgroup/memory" ]; thenmkdir -p $CGROUP_PATHecho "100M" > $CGROUP_PATH/memory.limit_in_bytesecho $$ > $CGROUP_PATH/cgroup.procs
fi# 4. 启动隔离环境
# `--pid`: 隔离进程 ID
# `--net`: 隔离网络
# `--mount`: 隔离挂载点
# `--fork`:  fork 进程
# `--map-root-user`: 映射 root 用户 (避免权限错误)
echo "正在启动容器..."
exec unshare `--pid` `--net` `--mount` `--fork` `--map-root-user` \chroot "$ROOTFS" /bin/sh# 5. 清理函数 (脚本退出时执行)
cleanup() {echo "清理容器资源..."if [ -d "$CGROUP_PATH" ]; thenrmdir "$CGROUP_PATH" 2>/dev/null || truefi
}
trap cleanup EXIT

运行与验证

赋予脚本执行权限并运行:

chmod +x mini-docker.sh
sudo ./mini-docker.sh

进入环境后,执行以下命令验证隔离是否生效:

# 1. 验证 PID 隔离 (应该只看到当前 shell 为 PID 1)
ps aux# 2. 验证 Namespace inode (应与宿主机不同)
ls -l /proc/self/ns/pid# 3. 验证文件系统隔离 (看不到宿主机的 /etc)
ls /etc

资源限制配置(Cgroups)

脚本中已包含简单的 memory 限制示例。不同发行版 cgroup 路径可能不同:

  • Cgroup v1: 路径通常为 /sys/fs/cgroup/memory/<name>,通过写入 memory.limit_in_bytes 限制。
  • Cgroup v2: 路径统一为 /sys/fs/cgroup/<name>,通过写入 memory.max 限制。

手动验证内存限制:

# v1 示例
echo "50M" > /sys/fs/cgroup/memory/test/memory.limit_in_bytes# v2 示例
echo "50M" > /sys/fs/cgroup/test/memory.max

常见坑与排查

  • 命令参数错误unshare 参数前不要加反引号,否则 Shell 会尝试执行命令而非传递参数。正确写法:unshare `--pid`
  • 权限问题:大多数 namespace 操作需要 root 权限,普通用户执行会报 operation not permitted
  • 网络不通:新建的网络 namespace 默认只有 lo 接口且处于 DOWN 状态。如需联网,需手动配置 veth pair 和网桥,或加入宿主机网络 namespace。
  • 进程逃逸:如果挂载配置不当(如未挂载 proc 文件系统),容器内进程可能访问宿主机敏感文件。建议在 chroot 后执行 mount -t proc proc /proc
  • 无法持久化:Shell 脚本启动的进程随脚本结束而消失,缺乏守护管理。生产环境请使用 Docker 或 Kubernetes。

原文链接:https://www.zjcp.cc/ask/11011.html

http://www.jsqmd.com/news/810649/

相关文章:

  • CS Demo Manager:免费开源CS比赛录像分析工具终极指南
  • VMware17 安装教程
  • 先进制程EPE挑战:从系统误差到量测革命,如何驯服边缘位置误差
  • 工程师的科幻恶搞视频指南:从乐高死星到Python式混搭
  • 2026年4月线上优质的青春期心理辅导考证报名哪里有,青少年叛逆/孩子休学/青少年心理咨询,青春期心理辅导考证报名推荐 - 品牌推荐师
  • 告别频点计算:用Python脚本为AD9361自动生成2400-2480MHz信道表(含VCO校准与锁定检查)
  • React开发环境搭建:三种方式获取核心JS文件(react.development.js等)
  • 大润发购物卡回收平台安全吗?圈内人说句大实话 - 京顺回收
  • 从测试执行到质量顾问:一个被低估的高价值转型方向
  • 利用Taotoken CLI工具一键配置多开发环境下的API密钥
  • JAMA Netw Open(IF=9.7)美国埃默里大学等团队:基于CT的原发肿瘤和转移性颈部淋巴结深度学习模型用于口咽癌结局预测
  • Windows上安装APK的终极指南:APK Installer完全教程
  • 从劝退到离不开:Vim新手入门实战博客(附高效技巧)
  • OpenHarmony应用签名实操指南:从文件结构到IDE配置
  • Java中的JUC容器类详解
  • 昆明闲置钻石回血避坑|5家正规平台实测,拒绝当冤种 - 奢侈品回收测评
  • 初次使用Taotoken从注册到完成第一个API调用的全流程
  • 2026年毕业生收藏:论文AI率太高怎么办?教你精准使用降AI率工具一键降ai - 降AI实验室
  • ModelSim入门实战(四): 参数化测试、自动比对与报告生成
  • 【Qlib框架】因子定义层及整体框架(alpha因子库+数据预处理+模型预测+IC分析+回测backtestdaily+风险分析+交易质量分析)
  • Bilibili视频下载终极指南:如何三步搞定大会员4K视频本地化
  • ChatGPT开发者实战指南:从API集成到应用部署的完整资源导航
  • JT808协议实战:用JTXQ模拟终端复现车道偏离报警全流程(附日志分析)
  • 2026哪个机构主任护师通过率高?过来人实测对比,避坑必看 - 医考机构品牌测评专家
  • 从开发者反馈看Taotoken标准OpenAI协议兼容性的实际表现
  • 088、Python网络服务开发:HTTP服务器
  • 2026年靠谱线下红娘机构推荐:合规婚恋服务机构选型与场景适配深度分析 - 产业观察网
  • 【题解】CF1603D Artistic Partition
  • 从零到一:51单片机蓝牙遥控车实战指南(附避坑要点)
  • 前端超能力:让浏览器听你指挥