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

【05-Docker底层原理】

Docker 的组件:

由五层组件组成流水线来构建一个完整的容器系统,每层组件只关注自己擅长的事情。

角色组件干什么
顾客Docker 客户端Docker CLI敲命令即点菜
前台收银Docker 守护进程(docker daemon )接单、协调后厨、管理所有菜品
后厨主管容器运行时 (containerd)菜品拆分成具体步骤
厨师OCI运行时 (runc)真正做菜的人
服务员容器垫片Containerd-shim上菜之后持续关注你这桌,别让菜凉了

为什么使用C/S架构?

当用户输入docker run nginx ,发生了什么。

你敲 docker run nginx → CLI 发请求给 dockerd → dockerd 通过 gRPC 转交 containerd → containerd 拉起 shim → shim 调用 runc → runc 调用 Linux 内核隔离技术创建并运行 Nginx 容器。

这样做的好处是`解耦`。各个组件职责分离与良好的扩展性,其核心组件并非单一进程而是协同工作的生态系统。

流程关键点解析

  • 协议分层:Client与Daemon间使用REST API,Daemon与containerd间使用gRPC,这是为了兼顾外部接口的通用性和内部调用的高性能。

  • 职责转移dockerd负责高层管理,但具体的容器创建任务通过gRPC"委托"给了containerd,实现了架构解耦。

  • 进程托管runc创建容器后即退出,由containerd-shim作为父进程托管容器,这确保了即使dockerd重启,容器也不会被意外终止。

容器的完整的生命周期

第1️⃣步:你敲了命令

docker run -d --name web -p 8080:80 nginx

Docker CLI 会把这条命令解析成一个HTTP REST请求发送给dockerd

第2️⃣步:dockerd 做"前台收银"该做的事

Dockerd 收到请求后,需要做一系列协调工作

镜像管理:检查本地是否存在 nginx 镜像,不存在则向 Registry 发起拉取,完成镜像分层落地存储。

存储准备:规划 overlay2 文件系统结构,调用 containerd snapshotter 创建 lowerdir、upperdir、workdir 目录,为后续联合挂载做准备。

网络准备:创建 veth pair 虚拟网卡,一端预置入容器网络命名空间、一端接入 docker0 网桥;分配容器内网 IP;配置 iptables NAT 端口转发规则,实现-p 8080:80端口映射。

配置整合:合并镜像内置元数据(ENV、CMD、EXPOSE)与命令行启动参数,整理容器运行配置模板。

下发请求:整理完毕全部容器配置,通过 gRPC 协议下发创建任务给 containerd。

关键点:dockerd 本身不直接操作 Linux 内核创建容器,它只是个"总调度"。

第3️⃣步:contarinerd 分发任务

containerd 分发任务(后厨主管统筹派活) containerd 通过 gRPC 接收到 dockerd 下发的容器创建请求,执行内部任务拆解分发:

  • 校验镜像元数据,确认容器文件系统运行环境就绪;

  • 为本次容器单独创建一个专属containerd-shim垫片进程;

  • 把整理好的容器运行参数传递给 shim,由 shim 作为中间代理去调用 runc,规避 containerd 主进程与容器强耦合问题。

补充作用:后续即便 containerd 进程重启、崩溃,容器也不会被终止,由 shim 持续托管容器状态。

第4️⃣步:runc真正创建容器

Runc 是整个链路最底层的一环,调用Linux 内核系统调用来创建容器。

  • 创建Namespace隔离环境:

  • 配置Cgroup实现资源管控:

  • 设置rootfs(通过Overlay2 挂载):

  • 通过chroot切换容器根目录:

  • 启动主进程

  • 完成容器启动工作后自身退出,并将容器运行状态反馈给 containerd-shim

第5️⃣步:containerd-shim 接管

containerd-shim成为容器 PID1 进程的父进程,长期驻留后台托管整个容器生命周期。

containerd-shim (PID: 12345)

└── nginx master (PID: 1, 容器内的1号进程)

└── nginx worker

└── nginx worker

  • 隔离守护进程,保容器不挂 shim 作为中间隔离层,容器归属 shim 管理。即使 containerd 重启或崩溃,容器依然正常运行,不被杀死。

  • 回收子进程,防止僵尸进程 自动调用wait()回收容器退出进程,读取退出码,上报给 containerd,避免产生僵尸进程。

  • 托管容器 IO 流与交互 统一接管容器标准输入输出,支撑docker logs查看日志、docker exec进入容器交互,维持通信通路。

  • 转发控制信号 宿主机docker stop/kill信号先给到 shim,由 shim 转发给容器主进程,实现容器正常启停。

  • 实时上报容器状态 持续将运行、暂停、异常、退出等状态通过 gRPC 上报给 containerd,最终同步到 dockerd,保证docker ps状态准确。

  • 生命周期收尾 容器销毁终止后,shim 完成清理工作并自动退出,整个容器流程闭环结束。

厨师 (runc) 做完菜下班,服务员 (shim) 留在桌边全程照看:饭菜(容器)不会因为后厨主管 (containerd) 离岗就撤掉;客人呼叫添茶、撤盘(操作容器、查看日志)由服务员中转;菜品吃完收盘(容器停止)服务员收尾离岗。

镜像分层:理解容器的"OverlayFS联合文件系统"

Docker 的镜像不是一个巨大的文件,而是一堆只读的薄层堆叠在一起。分层的目的是为了让项目在不同环境下复用。

最佳实践建议

  • 优化Dockerfile:将变动频率低的层放在前面(如基础镜像FROM),变动频率高的层放在后面(如添加应用ADD),以最大化利用层缓存,加速构建。

  • 合并层:在构建的最后阶段,可以考虑使用多阶段构建docker-squash工具减少层数,以精简镜像大小。

Overlay2:联合文件系统,是目前Liunx 主流的存储驱动。

核心概念是:

lowerdir (只读层) 多容器公用镜像底层,节约磁盘。

Upperdir (读写层):容器专属修改层,数据隔离,删除容器仅删除该层

Workdir (工作目录层): 写操作临时事务缓冲,防止文件损坏,用户不可见。

Merged (合并视图):上下层叠加后统一目录;读取自上而下查找,修改原有文件触发写时复制,改动最终落到 upperdir。

书本叠纸比喻:底层课本lowerdir是共用只读镜像,专属草稿纸upperdir存放容器所有修改,垫板workdir处理写时复制临时事务,肉眼所见完整书本就是两层合并后的merged统一视图。

配置示例(/etc/docker/daemon.json):

{ "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ] }

网络:容器怎么和外界通信?

Docker 提供了多种网络模式:

当你运行一个容器而未指定网络时,Docker会将其连接到默认的bridge网络(对应网桥docker0)。其内部实现如下:

宿主机外部网络(eth0: 192.168.1.100) │ ┌────┴────┐ │ NAT │ ← iptables 规则 └────┬────┘ │ ┌────┴────┐ │ docker0 │ (172.17.0.1/16) └──┬───┬──┘ │ │ veth1 veth2 │ │ eth0 eth0 (容器A) (容器B) 172.17.0.2 172.17.0.3

网络创建与通信流程:

  • Docker创建docker0虚拟网桥(默认网段172.17.0.0/16)。

  • 为每个容器创建一对veth设备,一端放入容器的Network Namespace(命名为eth0),另一端连接到docker0。docker0 只是桥接模式容器的网关。

  • 为容器的eth0分配IP(如172.17.0.2)。

  • 通过iptables设置NAT规则,实现容器访问外网和端口映射(-p 8080:80)。

使用默认bridge网络时,容器间只能通过IP通信。创建自定义网络可以启用容器名称发现。原理 :Docker为每个自定义网络内置了一个DNS服务器。当容器app2解析app1时,Docker DNS会返回app1在该网络中的IP地址。

数据持久化:为什么需要 Volume?

容器的可写层和容器的生命周期绑定了,当容器删除释放了,数据也会删除。

而且即使容器还在,可写层的性能也不如直接操作系统文件系统。

生产环境最佳实践

  • 使用命名Volumedocker volume create app_data,然后通过-v app_data:/app/data挂载。

  • 避免使用匿名Volume:不利于管理和迁移。

  • 谨慎使用Bind Mount:仅在需要直接编辑主机配置文件或进行开发调试时使用,docker run -v /host/test:/container/test nginx。-v 宿主机路径:容器路径。

Bind Mount 绑定挂载:用户指定宿主机已有路径,直接映射到容器,自由度高,适合挂载本地代码与外部配置;

Docker Volume 数据卷:Docker 自行管理存储空间,通过 docker volume create 创建,更适合业务数据持久化,不用手动维护宿主机目录。

内核基石:Namespace与Cgroups

容器隔离的本质是Linux内核中的N与C特性的组合使用。

Namespace 名称空间: 给进程创造一个"受限的视野",使用了6种Namespace
  • - PID Namespace: 它认为自己的PID是1

  • - Mount Namespace: 独立的文件系统挂载点 /、/proc、/sys

  • - Network Namespace: 独立的网络设备、IP、端口

  • - UTS Namespace: 独立的主机名

  • - IPC Namespace: 独立的信号量、消息队列、共享内存(进程间通信)

  • - User Namespace: 独立的用户和组ID映射(可选,增强安全

这不是虚拟机! 容器进程和宿主机进程运行在同一个内核上,只是通过 Namespace 限制了"它能看到什么"。

Cgroups:给进程"上枷锁", 解决的是进程组"能用多少资源";用于限制、统计和隔离进程组的资源(CPU、内存、IO等)。

一句话总结:Namespace 决定容器"能看到什么",Cgroups 决定容器"能用多少",OverlayFS 给容器一个独立的文件系统视图。三者组合,就是"容器"。

真实排查:用架构知识定位问题

  • 问题1:容器启动失败,报错"OCI runtime create failed"

思路:OCI 运行创建失败,说明到达了底层runc ,但是调用内核失败了。docker info 查看namespace、overlay 是否正常;查看详细日志 docker --debug 查看containerd日志(journalctl -u containerd)。

常见原因:内核版本太低,缺少内核模块,磁盘满,cgroup版本不兼容。

  • 问题2:容器内域名解析失败

思路:进入容器-exec 查看域名配置文件是否配置正常/etc/resolv.conf;

Ping 一下DNS服务器确认和服务器数据收发正常,检查防火墙是否拦截了;检查宿主机的DNS是否正常。

http://www.gsyq.cn/news/1620357.html

相关文章:

  • 最好用的 AI 标书工具排名(2026):全企业适配
  • 【编号955】黑龙江省-1990-2025年全国30m土地利用数据集
  • GPT-5.6 正式登场!多 Agent 能力封神,却被这个最大的难题坑惨了?
  • 从vNIC到物理网卡的完整链路追踪:VMware网络不通的8层协议栈穿透式排查法(含Wireshark过滤模板下载)
  • 抖音无水印下载终极指南:5分钟学会批量保存高清视频的完整教程
  • 大模型风口来袭!小白程序员必备通关攻略(收藏版)
  • 网络工程师转型安全渗透测试:从协议到内网的全栈实战指南
  • 抖音批量下载终极解决方案:5分钟掌握无水印视频批量下载技巧
  • AI短剧试运营看什么指标?先看开头留存、返工成本和素材余量
  • 速进!SeaTunnel 2.3.11 用 Docker 部署,实现 Kafka 同步 Hive/ES
  • Magisk Root终极指南:从零开始掌握Android设备Root完整教程
  • 骨聆小飞豆:刷新认知,重新定义运动骨传导耳机
  • 抖音内容批量下载难题:如何用开源工具实现高效无水印采集?
  • 从定做到非标定制:超声波清洗机定制厂家与品牌选择思路
  • codebase-memory-mcp 安装教程
  • 陶瓷PCB厚度如何选择:工程设计中的几个关键约束
  • 顶刊《AER》-通过ΔCoVaR测度系统性风险(Matlab代码实现)
  • Linux远程连接实操:Xshell、Xftp连接Ubuntu完整教程(附报错解决方案)
  • 【编号342】(安徽省)芜湖市基础地理矢量数据
  • 企业级应用漏洞复现:从CVE-2024-0490看接口权限与数据泄露防护
  • 老款Mac蓝牙修复终极指南:OpenCore Legacy Patcher完整解决方案
  • 2026年桌面风扇推荐:书桌办公、卧室夜间、多场景使用,三种需求三种配置
  • 阴阳师自动化脚本:解放双手的终极游戏助手
  • USB摄像头/加密狗/工业采集卡直通失效?揭秘VMware vSphere中被隐藏的USB 3.0 xHCI仲裁冲突机制},
  • 前端小厂二面(技术面)
  • 频域视角下的风险溢出网络:从DY溢出到BK溢出研究(Matlab代码实现)
  • 终极Nintendo Switch破解指南:TegraRcmGUI图形化工具完全教程
  • MC6470与PIC18F86J50的硬件连接与运动控制实现
  • PHP实现国密SM3哈希算法:从原理到实战优化
  • DamaiHelper大麦抢票脚本终极指南:告别手动抢票的焦虑时代