Docker 内部机制:深入剖析

大家好!我是大聪明-PLUS

首先是物理服务器 ------价格昂贵且效率低下。后来出现了虚拟机,使得在单个硬件上运行多个相互隔离的操作系统成为可能。但隔离的成本仍然很高:需要完整的操作系统副本、数GB的磁盘空间,以及几分钟的启动时间。

容器是下一个发展阶段。既然可以使用内核内置机制隔离 进程本身,为什么还要虚拟化整个硬件并运行完整的操作系统呢?这种方法要轻量级得多,速度更快,效率也更高。

图像和容器

  • 镜像文件 是一种模板或蓝图。它是一组不可变的、只读的文件、指令和依赖项,用于定义你的应用程序。

  • 容器 是镜像的运行实例。它提供了一个隔离的环境,应用程序就在这个环境中实际运行。当从镜像创建容器时,会添加一个轻量级的可写层。应用程序运行时发生的所有更改都会保存到该层中。

但这个盒子里面究竟藏着什么呢?让我们一探究竟。

第一部分:容器的惊天秘密......它们根本不存在

事实上,从Linux内核的角度来看, 并不存在所谓的"容器 "。存在的只是普通的Linux进程。只不过,这是一个在特殊条件下运行的进程。

这些条件是由两种内核机制产生的:

  1. 命名空间
    命名空间限制了容器内部可见的资源和进程。本质上,它们为每组进程创造了一种错觉,即它们拥有全局资源的独立实例,无论是网络协议栈、进程树还是文件系统。
  • PID 命名空间: 容器内的进程认为自己是第一个也是主要的进程(PID 1),并且看不到容器外的进程。

  • 网络命名空间: 容器拥有自己的虚拟网卡、路由表和 iptables。

  • 挂载命名空间: 容器拥有自己的文件系统树,与主机系统隔离。

  • ......以及其他(UTS、IPC、用户)。

  1. 控制组(Cgroups
    )它们并不隔离,而是 限制和控制 资源。控制组回答"多少人?"这个问题。
  • 限制 CPU、内存和磁盘 I/O 的使用。

  • 他们不允许一个"贪婪"的容器拖垮整个系统。

结论: 容器是一个非常普通的进程(例如 nginx 或 bash),只是通过 命名空间 与其他进程隔离,并通过 cgroups设置限制。

第二部分:图像剖析

如果容器是一个进程,那么镜像就是运行该进程的指令。

容器镜像由两个主要部分组成:

  1. 根文件系统(rootfs) -- 一个目录树,其中包含运行应用程序所需的全部软件:二进制文件、库和设置。不多不少。

  2. 一个包含元数据(指令)的 JSON 文件 。它描述了要运行的进程(CMD)、要设置的环境变量、要打开的端口以及要挂载卷的位置。

  

它是如何存储和传输的? 很简单!

该工具 还会tarrootfs JSON 文件打包成一个单独的归档文件。这种格式也是镜像存储在 Docker 镜像仓库(例如 Docker Hub)中的格式。每个镜像层也是 tar一个包含文件系统更改的归档文件。

以下是实际操作中的样子**------nginx镜像清单:**

复制代码
`[
  {
    `"RepoTags"`: [`"nginx:latest"`],
    `"Layers"`: [
      `"blobs/sha256/eb5f13bce993..."`,  
      `"blobs/sha256/dab69e9f41e9..."`,  
      
    ],
    `"LayerSources"`: {
      `"sha256:129b375526fc..."`: {
        `"mediaType"`: `"application/vnd.oci.image.layer.v1.tar"`,  
        `"size"`: `5120`,
        `"digest"`: `"sha256:129b375526fc..."`
      }
    }
  }
]`

这样做时 docker pull,你只需下载并解压这些归档文件,Docker Engine就会从中构建一个现成的容器文件系统。

第三部分:如何协同工作:Docker架构

当你输入 docker run nginx 命令时,后台会启动一个由四个组件组成的庞大系统。

  1. Docker引擎
  • 这是一个高级守护进程,您可以通过 CLI(docker run、docker build)与其通信。

  • 它处理你的命令,管理网络和卷,但 它本身并不运行容器。它将这项任务委托给底层服务器。

  1. containerd
  • 这是管理容器生命周期的主要运行时环境。

  • 它负责下载图像、管理存储,并将启动指令传递给下一个链接。

  1. runc
  • 正是这个工具可以访问 Linux 内核,从而将进程、文件系统、网络和其他容器资源与主机系统隔离。

  • 在收到来自 containerd(config.json 和 rootfs)的指令后,runc 直接与 Linux 内核交互。

  • 它创建新的命名空间,配置 cgroups,最后在这个隔离环境中启动我们的目标进程(例如 nginx)。

    重要提示: runc 进程启动后,会认为其工作已完成并退出。

  1. containerd-shim
  • 当容器进程的父进程(runc)终止时,该容器进程会发生什么?它由 containerd-shim 负责处理。
  • 这是一个轻量级进程,它将成为容器进程的新父进程。

    为什么有必要这样做?

    • Containerd-shim 允许您在不停止正在运行的容器的情况下重启或升级 containerd。

    • 将标准输入/输出流(stdin、stdout、stderr)重定向回 Docker Engine。

    • 监控流程状态并报告其完成情况。

结果

你的docker run命令 至关重要:

这样最终你的机器上就只会有一个独立的Linux进程

现在你掌握了这个技巧,Docker 就变成了一个强大的工程系统。祝你容器化之旅一切顺利 :-)

相关推荐
HLC++8 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室9 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
groundhappy12 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕12 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫13 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生14 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.1115 小时前
linux基础IO
linux·运维·服务器
BelongPanda17 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯17 小时前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算
2301_7779983417 小时前
Linux中断机制:操作系统如何高效运行
linux·运维·服务器