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 就变成了一个强大的工程系统。祝你容器化之旅一切顺利 :-)

相关推荐
张泽腾667 小时前
Ubuntu 扩容
linux·服务器·嵌入式硬件
RedMery7 小时前
Ubuntu切换wayland和x11
linux·运维·ubuntu
Shawn_CH7 小时前
Linux kmsg详解
嵌入式
uoscn7 小时前
Ubuntu24.04无操作卡死,无法唤醒问题以及内核版本切换记录
linux·ubuntu
一个写python的菜鸟8 小时前
华为服务器安装Todesk
linux·运维·服务器
小曾同学.com8 小时前
认识Linux 的shebang行,一个特殊的注释行
linux·解释器·shebang·/usr/bin/env
Thexhy8 小时前
CentOS7安装Redis全攻略
linux·经验分享·redis·学习
九鼎创展科技8 小时前
「有温度的陪伴」:基于全志 V821 的情感共鸣型实体机器人详解
linux·人工智能·嵌入式硬件·机器人
色空大师8 小时前
【linux查看日志】
java·linux·运维·日志