Docker源码阅读总结

news2024/12/26 0:23:40

Docker总架构图

在这里插入图片描述
客户端-服务器架构以及请求的发送,解析等原理不再赘述,这不是我们学习docker的重点。我们知道,Docker提供给了我们一个在隔离环境中运行的进程,那么我其实想深入探究的是

  1. 容器的网络是怎么在这个隔离的环境中与其他容器,与宿主机,与外界进行数据交换的。
  2. 镜像是一种什么样的结构,使得一个静态的镜像就生成多个动态运行的容器。
  3. 容器内的进程是怎么样去创建,运行的,这个进程和普通的宿主机的进程有哪些不同。

Docker通过一个叫做 libcontainer 的库实现了底层与容器创建运行相关的命令和顶层调用的隔离。在Docker0.9之前,Docker的底层命令依赖的是LXC,而在这之后,作为Docker的第一个子项目,libcontainer替代了LXC的功能,并且完全用Go语言实现。(实际还是用Go去执行具体的Linux命令)

下面就我上面提到的三点进行重点概述

Docker网络

在一台没有安装Docker的宿主机上,网络环境可能平淡无奇。但是,当用户开始启动并安装docker,一切都发生了变化。Docker Daemon有可能会在宿主机上新建一个网桥设备,以支持我们熟知的桥接模式
在这里插入图片描述

Docker Daemon首先要完成的任务是创建网桥,网桥可以由用户指定,也可以使用默认的docker0 。创建网桥的步骤如下:

  1. 确定网桥的IP地址
  2. 调用系统调用,创建网桥
  3. 将IP地址赋予网桥
  4. 启动网桥设备
    第一步是确定IP地址,先判断用户启动参数中是否制定了IP,没有的话从docker预留的网段中选择IP。
    第二步首先判断内核版本是否支持,然后调用系统调用创建网桥
    在这里插入图片描述
    第三步是将IP地址绑定到这个网桥上,最后一步为启动网桥。值得一提的是,这几步中涉及到的底层调用都是通过netlink进行的
    在这里插入图片描述
    这里我在总结的时候其实有个疑问,为什么可以为一个操作系统设置网桥,并且给他分配IP呢?Linux网桥的作用是什么?难道不应该是一个主机一个IP吗?

其实,一开始创建的docker0网桥,它还有另一个更为人熟知的名字,没错就是网卡。也就是说,docker是新建了一块虚拟网卡。这就不奇怪了,因为我们知道,一台机器可以有几个IP地址取决于它有几块网卡。但是又有一个疑问,docker0的IP地址并不为外界所熟知,那么外界如何和我们通信呢?答案就在Linux的一个内核参数,叫net.ipv4.ip_forward。这个参数指定了Linux系统当前对路由转发功能的支持情况;其值为0时表示禁止进行IP转发;如果是1,则说明IP转发功能已经打开。只要开启了这个,那么从外部访问容器内部时只需要访问宿主机的地址和对应的容器映射的端口,访问的数据包到宿主机上后经过ip包解析后通过目的port和iptables的规则会将数据包由eth0网卡转发至docker0网桥上进行下一步路由。

那我还有一个问题,为什么要额外建立一个虚拟的网桥,然后将数据包转发给它呢?直接都在eth0上面不好吗?其实,这样做的目的是为了让更好的抽象容器的概念。我们就是为了,让容器认为它独占了整台机器,所以就必须给容器一个虚拟的ip地址,让他自认为他是用这个ip与外界通信的。看上面的Docker桥接模式示意图,每个Container上有一个小的eth0,这就代表了每个容器都有自己的虚拟网卡,都有自己的ip,都有自己的从0-65535的端口。这些容器既可以通过docker0与外界通信,也可以通过docker0与其他容器通信。不管和谁通信,他都觉得自己和对方都是一台独立的机器,有自己的ip。这就是容器网络的本质。

Docker镜像

镜像是一种文件存储形式。提到Docker镜像,很容易联想到虚拟机镜像。镜像是一种文件存储形式,文件管理员可以通过技术手段将很多文件制成一个镜像。虚拟机的镜像存储有操作系统,文件系统,设备文件等,而Docker镜像与之相似,只不过不含操作系统内容,同时Docker镜像由多个镜像组合而成。它在容器视角而看是一个只读的layer

rootfs

rootfs是一个Docker容器在启动时其内部进程可见的文件系统视角
在这里插入图片描述
Docker利用Linux的Union Mount技术,将两层文件系统联合挂载,形成一种COW的文件系统
在这里插入图片描述
在这里插入图片描述

Images

Docker镜像采用了类似于roofts但是更为精妙的方式。为了让容器的迁移,构建的粒度更细,更为轻量化,我们可以将一个rootfs文件系统的内容拆分为多个镜像
在这里插入图片描述
如此一来,在不同的容器,不同的rootfs中的images可以服用在这里插入图片描述

镜像的构建:docker build

镜像是由Dockerfile中的内容构建而成的。Docker Daemon会根据Dockerfile中的内容,首先生成一个buildFile结构体,然后以解析出的内容为原材料,开始构建镜像
在这里插入图片描述
在这里插入图片描述
在逐行解析Dockerfile命令的过程中,对Dockerfile中的每一条除了FROM的指令,都会构建出一个新的image。因此,build的流程就是构建一个个image的流程。
Dockerfile的命令可以分为两类:
第一类命令修改上一层image的文件系统内容,比如,命令RUN在基于上一层image的容器中运行一条命令,这条命令很有可能修改上一层image的内容。命令ADD/COPY将Dockerfile所在宿主机目录的内容复制到上一层image
第二类命令仅仅修改景象的config信息。比如ENV会指定环境变量

这里我们重点分析一下RUN命令的执行流程

在这里插入图片描述
首先第一步是检查缓存,如果有缓存的话,直接返回即可,不必再重复构建。什么是缓存呢?我们在构建镜像时,buildFile的image属性存储的是我们的基础镜像,而config属性存储的是在基础镜像之上的一些配置信息

type Config struct {
	Hostname        string
	Domainname      string
	User            string
	Memory          int64  // Memory limit (in bytes)
	MemorySwap      int64  // Total memory usage (memory + swap); set `-1' to disable swap
	CpuShares       int64  // CPU shares (relative weight vs. other containers)
	Cpuset          string // Cpuset 0-2, 0,1
	AttachStdin     bool
	AttachStdout    bool
	AttachStderr    bool
	PortSpecs       []string // Deprecated - Can be in the format of 8080/tcp
	ExposedPorts    map[nat.Port]struct{}
	Tty             bool // Attach standard streams to a tty, including stdin if it is not closed.
	OpenStdin       bool // Open stdin
	StdinOnce       bool // If true, close stdin after the 1 attached client disconnects.
	Env             []string
	Cmd             []string
	Image           string // Name of the image as it was passed by the operator (eg. could be symbolic)
	Volumes         map[string]struct{}
	WorkingDir      string
	Entrypoint      []string
	NetworkDisabled bool
	OnBuild         []string
}

因此,我们在构建之前,只需要遍历本地镜像,只要存在一个镜像,此镜像的父镜像ID与当前buildFiled的image值相等,同时此镜像的所有config内容也与buildFile.config相同,则完全可以认为执行RUN命令产生的结果与此镜像的效果一致,直接使用该镜像即可。

如果找不到缓存,则只能手动创建镜像。怎么创建镜像呢?其实是先根据基础镜像创建一个容器,然后将容器挂载到文件系统上,然后运行这个容器,在容器中运行Dockerfile中的某行命令,然后将容器再提交为镜像,继续运行下一条命令。

Docker 容器

容器经常被用来与虚拟机比较,比较的维度也很多:容器运行时与宿主机共享同一个操作系统,而虚拟机是独立的操作系统、容器更加节省物理资源、容器到启动更加快,甚至达到秒级、容器的IO性能明显高于虚拟机…下面来具体看看容器是如何运行的,Docker是如何将 “死” 的镜像变为 “活” 的容器的。
在Docker中,容器的运行,即docker run其实分为两个步骤,一个是容器的创建,另一个是容器的启动。容器的创建源码是Create函数,它创建了一个container对象

在这里插入图片描述
创建主要是将一个“死”的镜像,变为一个“死”的容器,我们重点来看容器的启动,它将一个“死”的容器变为“活”的容器。
启动函数Start包含以下11个步骤:

  1. setupContainerDns
    为了让容器与外界建立通信,自然离不开DNS服务,用于确保域名的正常工作。如果网络模式是host模式,则和宿主机共享网络环境,不需要配置DNS。如若不然,则需要为容器内部配置DNS服务。DNS主要配置DNS服务器,如果用户在启动过程中或者配置文件中没有明确指定,则使用宿主机的配置。如果宿主机的不可用,则默认使用8.8.8.8和8.8.4.4,这两个为谷歌为我们提供的免费的DNS服务器IP地址。
  2. Mount
    容器的运行离不开文件系统的支持,Mount的主要任务是找到容器的根目录
  3. initializeNetworking
    初始化用户指定的网络模式(bridge、host等),进行相应的网络配置和初始化
  4. verifyDaemonSetting
    检查系统内核是否支持cgroup内存限制,以及是否支持网络接口间ipv4数据包的转发。
  5. prepareVolumesForContainer
    volume的存在使得Docker容器的存储可以实现持久话。该步为容器配置Volume结构体的信息
    在这里插入图片描述
  6. setupLinkedContainers
    容器间的link操作允许容器通过环境变量的形式发现另外一个容器,并在这两个容器之间传输信息。 该函数完成容器link环境变量的配置,建立多个容器之间的link关系。
  7. setupWorkingDirectory
    创建或切换至配置的容器工作目录
  8. createDaemonEnvironment
    完成容器环境变量的加载
  9. populateCommand
    填充Command对象,之前的所有配置信息都会体现在Command对象实例中
    在这里插入图片描述
  10. waitForStart
    启动容器进程,通过指定的namespace和配置信息fork进程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/431397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【花雕学AI】如何避免ChatGPT封号,安全稳定地使用ChatGPT的技巧和简单过渡办法

虽然ChatGPT 目前已经不是测试期了,它在 2021 年 11 月正式推出,并且在 2021 年和 2022 年后进行了多次更新,提升了真实性和数学能力等方面。但是,ChatGPT 的运算压力仍然很大,因为它需要处理海量的数据和请求&#xf…

ASUS ZenBook Duo 14 UX481电脑 Hackintosh 黑苹果efi引导文件

原文来源于黑果魏叔官网,转载需注明出处。(下载请直接百度黑果魏叔) 硬件型号驱动情况 主板ASUS ZenBook Duo 14 UX481 处理器• Intel Core i7-10510U • Intel Core i5-10210U 已驱动 内存Internal 4GB 2666 Changeable 8GB 2666 mem…

【WCH】CH32F203基于硬件I2C + SSD1306 OLED跑图形库

【WCH】CH32F203基于硬件I2C SSD1306 OLED跑图形库 🎈基于STM32图形库开源项目地址:https://github.com/hello-myj/stm32_oled📌相关篇《【WCH】CH32F203硬件I2C驱动SSD1306 OLED》📍《【WCH】CH32F203软件I2C驱动SSD1306 OLED》…

CountDownLatch背后的原理

前言: 在日常工作中常用到多线程,如果使用多线程处理那么就要考虑同步问题,一般我们会考虑使用加锁来解决。但是还有一些场景,如下: 场景:小升初考试,考生做题,监考老师要等待所有考…

论文阅读【2】-SepViT: Separable Vision Transformer论文结构漫谈与Python实现测试

可分离卷积ViT实现轻量级transformer结构1. 论文主要工作1.1 摘要内容1.2 写作动机(Motivations)1.2.1 Transformer Patch结构的巨大计算量问题1.2.2 Swin:针对计算量的优化1.2.3 Twins:针对边缘端部署优化1.2.4 Cswin&#xff1a…

【c#串口通信(2)】串口相关参数介绍

1、端口号(Port) 我们使用一个串口的时候,首先是要打开这个串口,那么我们怎么知道电脑上现在支持几个串口呢?对应的端口号又是什么呢? 由于我的电脑系统是window11,下面就以window11为例介绍如…

部分国产水文水动力模型介绍

一、HydroMPM模型 1、模型介绍 2016年度自立项目HydroMPM系统开发与集成完成的洪水分析模拟软件等成果经权威专家鉴定整体达到国际领先水平,HydroMPM_FloodRisk入选国家防总《全国重点地区洪水风险图编制项目可选软件名录》。成果应用项目100余项,累计…

spring自定义命名空间

命名空间 如果你曾经在配置datasource是用过properties文件储存我们的数据库连接信息&#xff0c;那么一定在xml文件中配置过这样的语句。 <context:property-placeholder location"classpath:jdbc.properties"/>而我们的spring当中很明显是没有这个context的…

【git】git的一些基础操作

文章目录一.git下载二.git初次操作1.生成公钥2.修改全局用户名和邮箱地址&#xff1a;3.本地仓库关联远端仓库4.本地初始化5.将项目上所有的文件添加到本地仓库6.提交到本地仓库7.创建main分支8.推送到main分支三.git其他操作1.develop分支2.查看分支3.切换分支4.查看分支历史一…

python wannier90 基于wannier90的*_hr.dat文件选取截断hopping绘制能带图

我们知道wannier90可以根据选取TMDs的轨道信息生成详细的hopping energy *_hr.dat文件&#xff0c;选取所有的hopping绘制起来的时候比较简单&#xff0c;但是我们发现取几圈的近似hopping也可以将band表示出来&#xff0c;类似的思想有Pybinding的三带近似&#xff08;DOI: 10…

区块链技术在软件开发中的应用

如果你是一名软件开发者或者IT从业者&#xff0c;你一定已经听说过区块链技术。区块链是一种基于密码学的分布式账本技术&#xff0c;被广泛应用于数字货币、金融、物联网等领域。但是&#xff0c;除了这些领域之外&#xff0c;区块链技术还可以在软件开发中发挥重要作用。本文…

CLIP 论文解读

文章目录模型训练推理实验与Visual N-Grams 相比较分布Shift的鲁棒性不足参考现有的计算机视觉系统用来预测一组固定的预订对象类别&#xff0c;比如ImageNet数据集有1000类&#xff0c;CoCo数据集有80类。这种受限的监督形式限制了模型的通用性和可用性。使用这种方法训练好的…

《花雕学AI》02:人工智能挺麻利,十分钟就为我写了一篇长长的故事

ChatGPT最近火爆全网&#xff0c;上线短短两个多月&#xff0c;活跃用户就过亿了&#xff0c;刷新了历史最火应用记录&#xff0c;网上几乎每天也都是ChatGPT各种消息。国内用户由于无法直接访问ChatGPT&#xff0c;所以大部分用户都无缘体验。不过呢&#xff0c;前段时间微软正…

Nginx实现会话保持,集群模式下session域共享

前言 生产环境下&#xff0c;多数系统为了应对线上多种复杂情况而进行了集群架构的部署&#xff0c;保证系统的高性能、价格有效性、可伸缩性、高可用性等。通常将生产环境下的域名指向Nginx服务&#xff0c;通过它做HTTP协议的Web负载均衡。 session是什么 在计算机中&…

13.广度优先搜索

一、算法内容 1.简介 广度优先搜索BFS&#xff08;Breadth First Search&#xff09;按照广度优先的方式进行搜索&#xff0c;可以理解为“尝试所有下一步可能”地穷举所有可行的方案&#xff0c;并不断尝试&#xff0c;直到找到一种情况满足问题问题的要求。 BFS从起点开始…

C语言——学生信息管理系统(数组)

文章目录一、前言二、目的三、框架1.菜单1.1主菜单1.2子菜单2.流程图2.1总流程图2.2开始流程图2.3增加学生信息流程图2.4.删除学生信息流程图2.5修改学生信息流程图2.6查询学生信息流程图2.7对学生信息排序流程图3.思路四、代码五、演示视频一、前言 因为最近是在赶进度总结&a…

无人驾驶--工控机安装autoware

时隔好久&#xff0c;又来写文章了&#xff0c;这次有高人指点&#xff0c;要系统的学习一下无人驾驶了。 使用的是易咖的底盘车&#xff0c;工控机是米文动力Apex Xavier II&#xff0c;基于autoware框架 首先是在工控机上安装autoware&#xff0c;工控是ubuntu18环境。 参…

Python入门教程+项目实战-9.2节: 字符串的操作符

目录 9.2.1 字符串常用操作符 9.2.2 操作符&#xff1a;拼接字符串 9.2.3 *操作符&#xff1a;字符串的乘法 9.2.4 []操作符&#xff1a;索引访问 9.2.5 [:]操作符&#xff1a;分片字符串 9.2.6 in操作符&#xff1a;查找子串 9.2.7 %操作符&#xff1a;格式化字符串 9…

为什么要做软件测试

随着信息技术的发展和普及&#xff0c;人们对软件的使用越来越普及。但是在软件的使用过程中&#xff0c;软件的效果却不尽如人意。为了确保软件的质量&#xff0c;整个软件业界已经逐渐意识到测试的重要性&#xff0c;软件测试已经成为IT 领域的黄金行业。本篇文章将会带领大家…

使用Tensorboard多超参数随机搜索训练

文章目录1超参数训练代码2远端电脑启动tensorboard完整代码位置https://gitee.com/chuge325/base_machinelearning.git 这里还参考了tensorflow的官方文档 但是由于是pytorch训练的差别还是比较大的&#xff0c;经过多次尝试完成了训练 硬件是两张v100 1超参数训练代码 这个…