乐于分享
好东西不私藏

Docker 源码解析:(一)架构及模块简介

Docker 源码解析:(一)架构及模块简介

大家好,我是费益洲。前面的系列文章主要讲述了 Docker 的核心技术。本系列主要讲述 Docker 容器在创建和启动的过程中,从源码的层面分析 Docker 的模块和组件的主体设计逻辑和功能实现。本文主要讲述 Docker 的整体设计架构、 Docker 的模块和组件的主要功能和调用关系。

Docker 架构演进

Docker 的架构演进经历了从单一工具到标准化生态系统的完整发展历程,其技术架构的演变反映了容器技术从初创到成熟的完整过程。

单体架构

Docker 最初诞生于 2013 年,由 DotCloud 公司(后更名为 Docker Inc.)开源发布。早期版本基于 LXC(Linux 容器)技术,通过封装 LXC 和 UnionFS 文件系统,实现了应用及其依赖的标准化打包。2014 年 Docker 1.0 正式发布,标志着 Docker 进入生产就绪状态,奠定了镜像、容器、仓库等核心概念的基础。

在 Docker 0.9 版本中,Docker 用自研的 libcontainer 替代了 LXC。libcontainer 是用 Go 语言编写的容器管理库,封装了 Linux 内核的 cgroups、namespaces、netlink 和 netfilter 等基础功能,使 Docker 摆脱了对 LXC 的依赖,实现了跨平台的可能性。

2015 年,Docker 发布了 runC,这是一个轻量级的跨平台容器运行时工具,可以直接利用 libcontainer 运行容器而无需通过 Docker 引擎。同年,Docker 与 CoreOS 等厂商共同成立了 OCI(开放容器倡议),旨在制定容器格式和运行时标准,Docker 将 libcontainer 捐赠给 OCI,推动了容器技术的标准化进程。

架构解耦与模块化

2016 年是 Docker 架构演进的关键年份。Docker 将 containerd 从核心引擎中分离出来,成为一个独立的守护进程,专门负责容器的生命周期管理。containerd 的分离使得 Docker 架构从单一软件演变为相互独立的组件体系:Docker Daemon → containerd → runC。这种分层解耦的架构使得 Docker 更加健壮、灵活和标准化。

现代 Docker 架构及各模块功能

Docker 经过多年的发展,架构形式从最初的单个整体模块演变为了通过标准接口协同工作的多个模块。本文主要对 Docker 在创建容器的过程中涉及到的模块的功能及各模块间的通信方式做简单介绍,具体的源码会在后续的文章说明。

以创建容器为例,Docker 所有组件及模块的整体调用顺序及架构如下所示:

Docker Client

Docker Client 是与 Docker 引擎交互的核心命令行工具,即用户平常用到的命令行 docker,它的主要功能就是将用户输入的命令行及参数解析为对 Docker Daemon 服务的 Restful 请求,并通过默认协议 Unix Socket 将请求发送到 Docker Daemon 服务。

Docker Registry

Docker Registry 是主要负责存储和分发 Docker 镜像的服务器。公共的 Registry 即 Docker Hub,这也是 Docker 默认的服务器。而私有的 Registry 一般都使用 Harbor 自行搭建,自行搭建的 Harbor 需要通过命令行 docker login 登录到该 Registry,登陆成功后会在默认目录中(~/.docker/config.json)生成相关配置。

Docker Daemon

Docker Daemon 是一个在宿主机上持续运行的守护进程,它的主要功能就是接收并处理 Docker Client 或其他客户端的 API 请求,并执行相应的容器操作。除此之外,Docker Daemon 还负责管理 Docker 容器、镜像、网络和存储等资源。

Containerd

Containerd 是一个在宿主机持续运行的守护进程,它专注于容器生命周期的管理。Containerd 是容器技术栈中承上启下的一个关键部分。向上提供基于 gRPC 协议的容器操控接口,供 Docker 等客户端调用,向下会通过 containerd-shim 去启动指定的 OCI 运行时(默认是 runc)来实际创建容器,进而实现与容器进程的解耦。

Containerd-Shim

Containerd-shim 以二进制的形式存在于宿主机中,通过 Containerd 调用启动一个 Containerd-shim 进程,该进程是一个轻量级进程,每个容器对应一个 shim 进程。它的主要职责包括:作为容器进程的父进程,即使 Containerd 守护进程本身重启,运行中的容器也不会受影响;保持容器的标准输入、输出和错误流,确保日志不会丢失;以及收集容器进程的退出状态并报告给 Containerd 。这种设计实现了容器生命周期与 Containerd 守护进程的解耦,提升了系统的稳定性和韧性。

runc

runc 一个轻量级、专一且符合开放标准的工具,直接与操作系统内核交互,负责实施容器隔离、资源管理,并掌控着容器从创建、运行到销毁的基本生命周期。它的核心任务非常专注:严格遵循 OCI(Open Container Initiative)的容器运行时标准,根据一个名为 config.json 的配置文件和一个根文件系统,来创建和运行容器,将容器的抽象定义转化为宿主机上一个个真正隔离的进程环境。

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » Docker 源码解析:(一)架构及模块简介

评论 抢沙发

3 + 6 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮