从 docker 到 runC
从 Docker 到 runC揭开容器运行时神秘面纱大家好我是你们的资深技术博主。今天我们来聊一个有趣又硬核的话题——从 Docker 到 runC。很多同学可能用过 Docker知道它能“打包应用、随处运行”。但你有没有想过Docker 是怎么在底层实现容器隔离的它背后到底调用了什么今天我们就从 Docker 这个“指挥官”出发深入到它手下的“执行者”——runC。## 什么是 Docker——一个漂亮的“管家”我们先简单回顾一下 Docker。Docker 是一个容器化平台它提供了从镜像构建、存储、拉取到运行的一整套工具链。简单说Docker 像一个“管家”你告诉它“我要跑一个 Nginx”它就会帮你拉镜像、创建容器、跑起来。但 Docker 本身并不直接创建容器。它依赖一个更底层的工具——runC。## 什么是 runC——真正的“执行者”runC 是一个轻量级的命令行工具它按照 OCIOpen Container Initiative标准来创建和运行容器。OCI 是一套容器格式和运行时的行业标准而 runC 是其参考实现。换句话说Docker 是一个高层工具它负责用户交互、镜像管理、网络等复杂功能而 runC 是底层工具它只做一件事让容器跑起来。我们可以把 Docker 想象成一个高级饭店的经理runC 则是后厨里专门负责炒菜的厨师。经理接单、协调、上菜但真正把食材变成菜的是厨师。## Docker 和 runC 的关系Docker 从 1.11 版本开始就采用了 runC 作为其默认的容器运行时。具体流程如下1. 用户输入docker run命令2. Docker 守护进程dockerd接收命令3. dockerd 调用 containerd容器管理守护进程4. containerd 启动 runC 实例5. runC 根据 OCI 规范创建并运行容器所以最终容器进程是由 runC 创建的Docker 只是“指挥官”。## 动手实践安装并运行 runC理论说太多不如动手跑一下。下面我们来看看如何安装 runC 并直接用它运行一个容器。### 安装 runC在 Ubuntu/Debian 上可以直接用包管理器安装bashsudo apt-get updatesudo apt-get install runc或者从 GitHub 下载预编译的二进制文件bashwget https://github.com/opencontainers/runc/releases/download/v1.1.12/runc.amd64chmod x runc.amd64sudo mv runc.amd64 /usr/local/bin/runc验证安装bashrunc --version### 用 runC 运行一个容器安装好后我们准备一个 OCI 标准的容器配置。OCI 标准规定容器的配置以 JSON 格式存放在config.json文件中根文件系统放在rootfs目录下。首先创建一个工作目录bashmkdir my-runc-containercd my-runc-container接下来我们需要一个根文件系统。最简单的办法是从 Docker 镜像导出bash# 拉取一个最小的 Alpine 镜像docker pull alpine:latest# 导出为 tar 包docker export $(docker create alpine:latest) -o alpine-rootfs.tar# 解压到 rootfs 目录mkdir rootfstar -xf alpine-rootfs.tar -C rootfs然后使用 runC 自带的工具生成配置bashrunc spec这会生成一个config.json文件里面包含了容器的默认配置。现在我们把它修改一下让容器启动后打印一句话。打开config.json找到process部分修改args为json{ process: { args: [/bin/sh, -c, echo Hello from runC! sleep 10], ... }}现在我们运行容器bashrunc run my-first-container你会看到输出Hello from runC!容器运行 10 秒后自动退出。恭喜你你已经直接使用 runC 运行了一个容器### 代码示例用 Go 调用 runC如果你是一个 Go 语言开发者还可以直接通过编程方式调用 runC。下面是一个简单的示例gopackage mainimport ( fmt os/exec log)func main() { // 准备 runC 命令指定容器 ID 和操作 cmd : exec.Command(runc, run, my-container) // 设置工作目录该目录下必须包含 config.json 和 rootfs cmd.Dir /path/to/container/config // 执行命令 err : cmd.Start() if err ! nil { log.Fatalf(启动容器失败: %v, err) } fmt.Println(容器 my-container 已启动) // 等待容器退出 err cmd.Wait() if err ! nil { log.Fatalf(容器运行出错: %v, err) } fmt.Println(容器已退出)}这个示例展示了如何用 Go 代码调用 runC。在实际的 containerd 源码中就是通过类似的机制来启动容器的。## runC 的底层原理Linux 内核特性runC 之所以能“隔离”进程是因为它利用了 Linux 内核的几大特性-命名空间Namespaces让容器有独立的进程、网络、挂载等视图。-控制组Cgroups限制容器的 CPU、内存等资源使用。-联合文件系统UnionFS实现分层镜像runC 本身不处理镜像但依赖挂载点。-Seccomp、Capabilities增强安全性。当我们运行runc run时它会1. 解析config.json2. 设置命名空间3. 配置 cgroups4. 挂载 rootfs5. 使用clone()系统调用创建新进程6. 最后通过exec()执行用户指定的命令## Docker 如何调用 runC为了让大家更清楚我们写一个简单的 Python 脚本模拟 Docker 调用 runC 的过程pythonimport subprocessimport osimport json# 模拟 Docker 创建容器配置def create_config(): config { ociVersion: 1.0.2-dev, process: { args: [/bin/sh, -c, echo Hello from simulated Docker!], env: [PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin], cwd: / }, root: { path: rootfs # 根文件系统路径 }, linux: { namespaces: [ {type: pid}, {type: network}, {type: ipc}, {type: uts}, {type: mount} ] } } with open(config.json, w) as f: json.dump(config, f, indent2)# 模拟 Docker 调用 runCdef run_container(): container_id simulated-container # 设置工作目录 work_dir /tmp/my-container os.makedirs(work_dir, exist_okTrue) os.chdir(work_dir) # 创建配置 create_config() # 假设 rootfs 已经存在 if not os.path.exists(rootfs): print(错误: rootfs 目录不存在) return # 调用 runC print(f模拟 Docker 调用 runC 运行容器: {container_id}) result subprocess.run( [runc, run, container_id], capture_outputTrue, textTrue ) print(标准输出:, result.stdout) print(标准错误:, result.stderr) if result.returncode 0: print(容器运行成功) else: print(f容器运行失败返回码: {result.returncode})if __name__ __main__: run_container()这个脚本展示了 Docker 底层的工作流程生成 OCI 配置然后调用 runC 执行。当然Docker 的实际实现要复杂得多但核心思想是一样的。## 总结今天我们走了一遍从 Docker 到 runC 的探索之旅。总结一下1.Docker 是高层工具提供了完整的容器生态链包括镜像管理、网络、存储等。2.runC 是底层工具专注于按照 OCI 标准创建和运行容器是容器真正的执行者。3.Docker 调用 containerdcontainerd 再调用 runC形成“Docker → containerd → runC”的三层架构。4. runC 利用 Linux 内核的命名空间、cgroups等特性实现隔离。5. 通过直接使用 runC我们可以更深入地理解容器本质容器本质上就是加了隔离和限制的普通进程。理解了 runC你就能明白 Docker 并不是什么黑魔法。它只是一个漂亮的壳里面包裹着 Linux 内核提供的能力。下次你用docker run时可以想想背后那个默默工作的 runC——它才是那个真正让容器“跑起来”的英雄。希望这篇文章对你有帮助如果你有任何问题欢迎在评论区留言。我们下期再见

相关新闻

Spring Cloud:分布式系统的“粘合剂”(四)

Spring Cloud:分布式系统的“粘合剂”(四)

专栏:Spring Cloud 个人主页:手握风云 目录 一、负载均衡 1.1. 问题 1.2. 定义 1.3. 分类 二、Spring Cloud LoadBalancer 2.1. 快速上手 2.2. 负载均衡策略 2.3. 底层原理 三、多机部署 3.1. 前置准备 3.2. Maven 项目打包 3.3. 服务器 Jar…

2026/7/27 5:57:45 阅读更多 →
Unity责任链模式实战:游戏事件处理与代码解耦

Unity责任链模式实战:游戏事件处理与代码解耦

1. 项目概述:为什么Unity开发者需要掌握责任链模式?如果你在Unity里写过稍微复杂一点的逻辑,比如处理一个UI按钮点击后要经过登录验证、资源检查、冷却判断、最终执行一连串操作,或者处理一个游戏事件需要被多个系统(音…

2026/7/27 5:56:44 阅读更多 →
Claude Opus在ARC-AGI-3基准测试创SOTA:AGI评估标准变革与开发实践

Claude Opus在ARC-AGI-3基准测试创SOTA:AGI评估标准变革与开发实践

最近在 AI 圈子里,一个消息引起了不小的震动:Claude Opus 在 ARC-AGI-3 基准测试中创下了新的 SOTA(State-of-the-Art)成绩。但如果你以为这只是又一个“模型刷榜”的新闻,那就错过了真正重要的信息。这个成绩背后真正…

2026/7/27 5:56:44 阅读更多 →

最新新闻

CTF逆向工程入门:从零构建知识体系与实战路径

CTF逆向工程入门:从零构建知识体系与实战路径

1. 从零到一:逆向工程在CTF中的角色与价值 如果你对网络安全竞赛(CTF)感兴趣,尤其是看到那些“逆向工程”(Reverse Engineering)题目时,既觉得酷炫又感到无从下手,那么这篇文章就是为…

2026/7/27 6:09:55 阅读更多 →
Ubuntu服务器源码编译OpenCV C++开发环境完整指南

Ubuntu服务器源码编译OpenCV C++开发环境完整指南

1. 项目概述与核心需求解析 在服务器上部署C版本的OpenCV,这听起来像是一个基础操作,但实际操作过的朋友都知道,这绝对是个“一步到位”的挑战。尤其是在生产环境或远程开发服务器上,你需要的不仅仅是一个能跑起来的库&#xff0…

2026/7/27 6:09:55 阅读更多 →
Android反调试实战:绕过libmsaoaidsec.so对Frida的检测机制

Android反调试实战:绕过libmsaoaidsec.so对Frida的检测机制

1. 项目概述:当Frida遇上libmsaoaidsec.so在移动安全研究,特别是Android应用逆向与动态分析领域,Frida几乎成了人手必备的瑞士军刀。它能让我们在运行时注入JavaScript脚本,去Hook函数、修改逻辑、分析数据流,效率极高…

2026/7/27 6:09:55 阅读更多 →
大语言模型选型指南:从性能测试到生产环境迁移策略

大语言模型选型指南:从性能测试到生产环境迁移策略

这类模型发布消息,最值得先看的不是宣传标题,而是它到底在什么条件下能跑出宣称的效果,以及普通用户能不能低成本用起来。“性能超越,价格减半”听起来很吸引人,但落地时我更关心的是:它支持哪些具体任务类…

2026/7/27 6:09:55 阅读更多 →
iOS抖音流量拦截与逆向分析:mitmproxy实战指南

iOS抖音流量拦截与逆向分析:mitmproxy实战指南

1. 项目概述:为什么我们要拦截抖音的流量? 如果你是一名移动应用开发者、安全研究员,或者是对数据流动充满好奇的技术爱好者,那么“抓包”这个词对你来说一定不陌生。简单来说,抓包就是截获并分析设备与服务器之间传输…

2026/7/27 6:09:55 阅读更多 →
MCP、RAG与Agent:现代智能系统架构核心技术解析

MCP、RAG与Agent:现代智能系统架构核心技术解析

1. 技术架构三剑客:MCP、RAG与Agent核心解析当我们在讨论现代智能系统架构时,经常会遇到三个关键术语:MCP(任务控制协议)、RAG(检索增强生成)和Agent(智能代理)。这三个概…

2026/7/27 6:08:54 阅读更多 →

日新闻

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →
SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

1. 项目概述:从寄存器手册到实战指南 如果你手头有一份类似德州仪器(TI)TMS320x240xA系列DSP的SPI模块技术手册,看着里面密密麻麻的寄存器位定义、时序图和公式,是不是感觉头大?这份资料虽然权威&#xff0…

2026/7/27 0:00:54 阅读更多 →
【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/27 4:33:59 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/27 4:01:12 阅读更多 →

月新闻