当前位置:首页>Linux>搞懂 Linux 内核容器技术,才算真正吃透 Linux 内核底层

搞懂 Linux 内核容器技术,才算真正吃透 Linux 内核底层

  • 2026-07-02 16:47:17
搞懂 Linux 内核容器技术,才算真正吃透 Linux 内核底层

容器,简单来说,是一种自包含的软件打包技术。

它将应用程序及其运行所需的一切依赖,如代码、运行时环境、系统工具、系统库等,统统封装在一个独立的运行环境中 。无需再为 “应用在我电脑能跑,上线就崩” 这类环境差异问题而头疼,真正实现了 “Build once, Run anywhere”(一次构建,到处运行)。

一、容器是什么?

1.1 容器技术的定义

从技术原理来讲的话,容器是基于 Linux 内核的特性,实现了轻量级的进程隔离。

通过巧妙运用命名空间(Namespaces)和控制组(Cgroups),容器内的进程拥有自己独立的资源视图,彼此之间互不干扰,就像在不同的小世界里运行。这不仅保障了应用的稳定运行,启动速度可达到秒级,资源利用率大幅提高,单机可以轻松承载数千个容器实例 ,这是传统部署方式难以企及的。

1.2 容器与虚拟机区别

很多人喜欢把容器说成是“轻量级虚拟机”,这说法吧,也不是全错,但本质上南辕北辙。

容器的核心是一组被内核“欺骗”的进程,你把它理解成虚拟机,就默认它有独立内核、独立硬件抽象层。实际上容器啥也没虚拟,它跑的就是普普通通的 Linux 进程,只不过内核通过某种手段(Namespace 和 Cgroups)让这个进程以为自己独占整台机器。

虚拟机是基于 Hypervisor(虚拟机监视器)实现的硬件级虚拟化。Hypervisor 如同一个中介,在物理服务器硬件之上模拟出一套完整的硬件环境,每个虚拟机都需要安装独立的操作系统(Guest OS),拥有自己专属的 CPU、内存、磁盘等资源。这就像是在一台物理电脑里又虚拟出多台独立的电脑,每台都能独立运行不同的操作系统和应用,隔离性极强,但代价是资源开销大。虚拟机镜像动辄数 GB,启动时间往往以分钟计算,在资源利用率和启动效率上存在明显短板。

反观容器,它属于操作系统级虚拟化,所有容器共享宿主机的 Linux 内核 。容器利用命名空间实现进程、网络、文件系统等资源的隔离,通过 Cgroups 来限制每个容器对 CPU、内存等资源的使用。容器只包含应用及其依赖,镜像体积通常在 MB 级别,启动速度能达到秒级甚至毫秒级,性能表现接近原生应用。在单机部署密度上,容器更是展现出碾压虚拟机的优势,能极大提升硬件资源的利用效率。

二、核心机制:命名空间(Namespaces)

2.1 命名空间技术:进程隔离的基础

先来个不那么严谨但好懂的说法:Namespace 就是内核给进程画圈。

一个进程被放进圈里,它只能看到圈里的东西。圈外的进程、文件系统、网络接口——统统看不见。不是说它们不存在,而是内核在“视野”层面做了过滤。

Linux 里 Namespace 的实现方式是给每个进程绑一组“命名空间标识符”。当一个进程访问系统资源(读 proc、枚举网络接口、发起 IPC),内核先去查它在哪个空间里,然后只返回属于那个空间的内容。Namespace 把“系统全局资源”包装成“每个空间独立的实例”——比如你在容器里 ps aux 只看到容器内那几个进程,不是宿主机 2000 多个,因为内核给你看的 PID 树是假的,或者说,是“被隔离过”的树。

这机制和 chroot 很像但比它强太多了。chroot 只改了根目录的映射,Namespace 可以隔离六七个维度:PID、Mount、Network、UTS、IPC、User,再加上后来加的 Cgroup Namespace。每一项都是独立的“视界”。

2.1.1 进程隔离(PID Namespace)

PID Namespace 是我最喜欢用的,你跑个容器进去 ps aux,PID 都是从 1 开始排,这个 1 号进程在容器里就是 init,它是所有进程的父进程,负责收养孤儿进程。

但你回到宿主机上 ps aux | grep 一下那个容器的进程,你会发现它的 PID 是别的数字,比如 18723。这种“双重身份”怎么做到的?内核在 PID Namespace 里维护了一个 PID 映射表。同一个进程在内核里只有一个“真 PID”,但在不同的 PID Namespace 里可以有不同“视图 PID”。

有一回我排查一个问题,在容器里 strace 一个进程的 PID 子进程,在宿主机用 nsenter -t <宿主机PID> -p 进去挂接——搞半天 PID 对不上,最后发现我进错了 Namespace。真丢人。这种低级错误写出来也挺好,提醒自己别犯懒。

2.1.2 文件系统隔离(Mount Namespace)

Mount Namespace 主要负责隔离文件系统的挂载点,它让每个容器都拥有自己独立的文件系统视图,简单来说,容器内看到的文件系统结构与宿主机以及其他容器是相互独立的,就像是每个容器都有自己专属的根目录。

在 Linux 系统中,文件系统的挂载点决定了进程对文件的访问路径,通过 Mount Namespace,容器可以拥有自己的挂载点集合,这些挂载点仅在容器内部可见。例如,容器可以将宿主机的某个目录挂载到容器内的指定位置,但这个挂载操作只对当前容器有效,不会影响宿主机和其他容器的文件系统布局 。

容器在启动时,会基于 Mount Namespace 构建自己的文件系统层级,结合联合文件系统(UnionFS),容器可以将多个只读层和一个可写层叠加在一起,形成一个完整的文件系统,容器内的进程对文件的读写操作都发生在这个独立的文件系统中,不会泄露到宿主机或其他容器中,确保了容器环境的独立性和安全性 。

2.1.3 网络隔离(Network Namespace):独立的网络栈

Network namespace 给每个容器独立的网络栈。自己的 lo 接口、IP 地址、路由表、iptables 规则。容器间通信靠 veth pair,一端在容器里,一端在宿主机上,像虚拟网线一样连着,Docker 默认的 bridge 网络就是这么玩的,你用 ip netns exec 命令进去看,会感觉像开了上帝视角。

2.1.4 UTS Namespace:主机名与域名的隔离

UTS Namespace 主要负责隔离主机名和域名,允许每个容器设置自己独立的主机名和 NIS(Network Information Service)域名 。这使得容器在网络中可以呈现为一个独立的节点,拥有自己独特的标识。

在容器环境中,不同容器可以拥有不同的主机名,彼此之间互不干扰。IPC namespace 管 System V IPC 和 POSIX message queues,进程间通信隔离了,User namespace 最有意思,能把容器里的 root(UID 0)映射成宿主机的普通用户,大大降低了逃逸风险。

2.1.5 IPC Namespace:进程间通信隔离

IPC Namespace 隔离的是 System V IPC 对象和 POSIX 消息队列。这意味着容器 A 里创建的共享内存段,容器 B 看不见也访问不到。这个维度在一般应用场景里用到的不多,但对安全隔离很重要——你不能让恶意容器通过共享内存去偷隔壁容器的数据。

2.1.6 User Namespace:用户 ID 映射与安全隔离

这个太重要了,单独多讲几句。

User Namespace 允许你在容器里是 root(UID 0),但在宿主机上其实是一个普通用户,比如 UID 65534(nobody)。怎么做到的?内核维护了一个 UID/GID 映射表。比如说你可以配置:容器内的 UID 0 映射到宿主机的 UID 1000,容器内的 UID 1000 映射到宿主机的 UID 2000,以此类推。

这个特性是容器安全的基石,没有 User Namespace 的时候,一旦有人从容器里逃逸出来,拿到了 root 权限,宿主机直接沦陷。有了 User Namespace 后,你逃出来了也就是个普通用户,权限非常有限。

但这里有个坑——User Namespace 和很多文件系统操作有兼容性问题。我记得好像是三年前我在 Docker 里开 User Namespace 然后挂载 NFS,直接炸了,日志里全是权限错误。原因是 NFS 服务端不认识你的 UID 映射。这类问题至今在部分场景下还存在,所以生产环境启用 User Namespace 之前要做充分测试。

2.2 命名空间实战

咱们动手搓一个“迷你容器”,先来个最简版。

用 unshare 命令创建一个隔离的 bash 环境,隔离 UTS、PID 和 Mount Namespace:

# 创建一个隔离的 shell,拥有独立的 PID、UTS 和 Mount 命名空间sudo unshare --fork --pid --mount --uts --mount-proc /bin/bash

跑完这行命令,你就进了个“半容器”。ps aux 一下,只看到 bash 和你正在运行的进程。hostname test-container 改个主机名,退出后宿主机不受影响。

想更自动化一点?

用 C 代码直接调用 clone() 系统调用,这其实就是容器运行时的底层做法:

#define _GNU_SOURCE#include <sched.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>#define STACK_SIZE (1024 * 1024)static char child_stack[STACK_SIZE];int child_func(void *arg) {    /* 进入新的 PID/UTS/Mount Namespace */    sethostname("mini-container", 15);    execl("/bin/bash", "/bin/bash", (char *)NULL);    return 0;}int main() {    int flags = CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD;    pid_t child = clone(child_func, child_stack + STACK_SIZE, flags, NULL);    if (child == -1) {        perror("clone failed");        exit(1);    }    waitpid(child, NULL, 0);    return 0;}

编译运行:gcc -o mini-container mini-container.c && sudo ./mini-container

然后你就得到了一个手工版的“容器”,主机名独立、进程树独立、挂载点独立。

  • • clone() — 创建新进程并带入指定 Namespace
  • • unshare() — 让当前进程脱离某个 Namespace
  • • setns() — 让当前进程加入一个已存在的 Namespace

三、资源管控核心:控制组(Cgroups)

3.1 Cgroups 的作用

在容器技术的体系中,命名空间(Namespaces)解决了 “资源隔离” 的问题,让容器内的进程仿佛运行在独立的小世界里,互不干扰 。而控制组(Cgroups)则聚焦于 “资源定量管控”,它决定了每个容器能使用多少资源,防止单个容器肆意挥霍宿主机资源,影响其他容器或宿主机的正常运行。

想象一下,宿主机是一座公寓大楼,每个容器就是大楼里的一户住户。命名空间为每个住户划分了独立的居住空间,而 Cgroups 则为每个住户规定了水电等资源的使用额度。比如,通过 Cgroups,我们可以限制某个容器最多只能使用 1 个 CPU 核心、512MB 内存以及每秒 100MB 的磁盘读写带宽 。这样一来,即使某个容器内的应用出现异常,疯狂占用资源,也不会拖垮整栋 “大楼”,保障了其他容器的稳定运行和资源的合理分配。

Cgroups 通过一系列的子系统(Subsystem)来实现对不同类型资源的管控。常见的子系统包括 cpu 子系统(控制 CPU 分配)、memory 子系统(限制内存使用)、blkio 子系统(管理块设备 I/O)等 。每个子系统都提供了对应的配置参数和接口,用户可以根据实际需求,灵活地为容器或进程组设置资源限制策略。

3.2 Cgroups 核心

Cgroups 采用树状的层级结构,在这个层级结构中,每个节点都代表一个控制组(Cgroup),可以将进程加入到不同的控制组中。根控制组是整个层级树的顶端,所有其他控制组都是它的子节点。子控制组会继承父控制组的资源限制设置,同时也可以拥有自己独特的限制规则,这种层级结构使得资源管理更加灵活和高效。

以一个 Web 服务集群为例,我们可以创建一个名为 “web-services” 的父控制组,限制其总的 CPU 使用量为 4 核。然后,在这个父控制组下,为每个 Web 服务器实例创建一个子控制组,如 “web-server-1”“web-server-2” 等 。每个子控制组可以根据自身负载情况,进一步细化 CPU、内存等资源的分配,比如 “web-server-1” 设置为最多使用 1 核 CPU 和 1GB 内存,“web-server-2” 设置为最多使用 2 核 CPU 和 2GB 内存 ,它们的总资源使用不会超过父控制组的限制。

子系统(Subsystem)是 Cgroups 实现资源管控的核心模块,每个子系统负责管理一种特定类型的资源 。比如,cpu 子系统通过控制 CPU 时间片的分配,来限制进程组的 CPU 使用率;memory 子系统通过设置内存使用上限,防止进程组过度占用内存;blkio 子系统则通过控制块设备的 I/O 操作,限制进程组对磁盘的读写速率 。不同的子系统可以根据实际需求,挂载到不同的控制组层级上,实现对资源的精细化管理。

控制器(Controller)是子系统的具体实现,它负责将资源限制策略应用到控制组中的进程上 。每个子系统都包含多个控制器,每个控制器对应一个具体的资源限制参数。以 cpu 子系统为例,它包含了 cpu.cfs_quota_us 和 cpu.cfs_period_us 等控制器 。其中,cpu.cfs_period_us 定义了 CPU 调度的周期(单位为微秒,默认值是 100000,即 100ms),cpu.cfs_quota_us 则定义了在这个周期内,进程组最多可以使用的 CPU 时间 。通过调整这两个参数,我们可以精确地控制进程组的 CPU 使用率。

3.3 资源管控实战

来,直接实操。

先创建一个叫 myapp 的控制组,限制它最多用 256M 内存,CPU 权重设低一点:

# 创建子 cgroupsudo mkdir /sys/fs/cgroup/myapp# 看看有哪些控制器可用cat /sys/fs/cgroup/myapp/cgroup.controllers# 输出可能是:cpuset cpu io memory pids ...# 内存硬上限 256MBecho "268435456" | sudo tee /sys/fs/cgroup/myapp/memory.max# CPU 权重(相对于同级 cgroup,数字越低分到的 CPU 时间越少)echo "100" | sudo tee /sys/fs/cgroup/myapp/cpu.weight# 限制最多进程数echo "50" | sudo tee /sys/fs/cgroup/myapp/pids.max# 把当前 shell 加进这个 cgroupecho $$ | sudo tee /sys/fs/cgroup/myapp/cgroup.procs

验证一下:cat /proc/self/cgroup,你会看到当前进程已经归属 myapp 组了。然后跑个 stress-ng --vm 1 --vm-bytes 300M——你会发现 OOM Killer 果断出手,因为 300M > 256M。

Docker 做的其实就是把这些步骤自动化。你执行 docker run --memory=256m --cpus=1,Docker 在后台创建对应的 cgroup、写限制值、把容器进程 PID 写入 cgroup.procs 文件。

3.4 Cgroups 与容器的资源隔离

继续说上面那个 myapp 的例子。我再建一个 app-highprio 组,给更高 CPU 权重:

sudo mkdir /sys/fs/cgroup/app-highprioecho "1000" | sudo tee /sys/fs/cgroup/app-highprio/cpu.weightecho "536870912" | sudo tee /sys/fs/cgroup/app-highprio/memory.max

现在把两个进程分别放进这两个组,同时跑 CPU 密集型任务,你会观察到 app-highprio 组的进程获得更多 CPU 时间片——比例大约是 1000:100 = 10:1(严格来说不是精确比例,实际还受调度器其他因素影响,但大致方向是对的)。

这就是 Cgroups 的威力:在不改变应用代码、不虚拟硬件的情况下,通过内核调度器实现了多租户间的资源公平分配。

3.5 Cgroups API 与工具链

除了直接操作文件,还有一套命令行工具,cgcreatecgexec来自libcgroup工具包(v1 时代用得多),v2 推荐用systemd` 的 slice 机制。

不过我个人更喜欢直接操作文件,透明度高。systemd-cgls 可以看 cgroup 树结构,systemd-cgtop 实时看资源使用排行——这俩命令我在日常运维中用得最多。

四、文件系统(UnionFS)与容器镜像

4.1 容器镜像的本质

容器的镜像本质是啥呢?

是一个分层叠加的只读文件系统,每一条 Dockerfile 指令生成一层。FROM ubuntu:22.04 是第一层,RUN apt-get install nginx 是第二层,COPY app /app 是第三层……每一层都是一个不可变的目录树。容器启动时,在这些只读层之上叠加一个可写层,形成一个统一的文件视图。

这种分层结构有超过优势,比如镜像层的复用性,不同的容器镜像如果依赖相同的基础层,如都基于 ubuntu:latest 基础镜像,那么这个基础层只需在宿主机上存储一份,多个镜像可以共享,大大节省了存储空间 。在构建镜像时,Docker 会根据指令的执行顺序,依次创建每一层,并为每一层生成唯一的哈希标识 。当再次构建相同指令的镜像层时,Docker 可以直接复用之前的缓存层,无需重新执行指令,极大地提高了构建效率 。

当容器启动时,会在这些只读层之上挂载一个可写层(Writable Layer) 。所有对容器内文件系统的写操作,如创建文件、修改文件内容等,都发生在这个可写层中 ,而底层的只读镜像层始终保持不变。这就好比在一幅已经画好的油画上覆盖一层透明的薄膜,在薄膜上进行的任何涂鸦都不会影响到下面的油画。这种设计既保证了镜像的不可变性,使得镜像可以被安全地共享和分发,又为容器运行时的动态修改提供了支持 。

4.2 UnionFS 原理

UnionFS(联合文件系统)是实现容器镜像分层存储和读写分离的核心技术,它的工作原理基于 “写时复制”(Copy-On-Write,简称 CoW)机制 。简单来说,当容器需要读取文件时,UnionFS 会按照从上层到下层的顺序,在各个只读层中查找目标文件 。如果在某一层找到了文件,就直接从该层读取,不会对文件进行复制 。例如,容器要读取 /etc/nginx/nginx.conf 配置文件,假设这个文件位于基础镜像层,UnionFS 会直接从基础镜像层加载该文件,整个过程高效且快速 。

当容器需要修改文件时,“写时复制” 机制就会发挥作用。如果要修改的文件位于只读层,UnionFS 会先将该文件从只读层复制到可写层,然后在可写层中进行修改 。后续对该文件的所有读取操作,都会从可写层获取修改后的版本 。比如,容器内要修改 nginx.conf 文件,UnionFS 会把 nginx.conf 从只读镜像层复制到可写层,在可写层中完成修改后,再次读取 nginx.conf 时,返回的就是可写层中修改后的内容 ,而底层的只读镜像层中的 nginx.conf 文件依然保持原样 。

当容器删除一个文件时,实际上并不会真正删除只读层中的文件,而是在可写层中创建一个特殊的 “删除标记” 文件(也称为 whiteout 文件) 。这个标记文件会覆盖掉只读层中的原始文件,使得在容器内看起来文件已被删除 。这样的设计保证了只读镜像层的完整性,同时也实现了文件删除操作在可写层的独立管理 。

4.3 主流 UnionFS 实现

OverlayFS 是目前的事实标准。自 Linux 内核 3.18 合入主线后,它把 AUFS 和 Device Mapper 基本全淘汰了。overlay2 驱动多 lowerdir 原生支持,不用像老 overlay 那样依赖硬链接来提升 inode 利用率,效率高很多。

AUFS 曾经是 Docker 默认的存储驱动,但一直没进内核主线,维护太痛苦。Device Mapper 性能还行但配置复杂,thin pool 出问题的时候排查起来很头疼——有一次生产环境的 thin pool 满了,容器全部变成只读,后来我把线上所有环境全迁移到 OverlayFS,舒服了。

OverlayFS 的挂载结构:

  • • lowerdir:只读的镜像层(可以有多个,多个之间用冒号分隔)
  • • upperdir:容器的可写层
  • • workdir:内核操作需要的工作目录(用户不可见)
  • • merged:对外呈现的统一视图

容器启动时,Docker 把这些目录组装好,然后执行一次 mount -t overlay 挂载,容器的根文件系统就出来了。退出时 umount,overlay 卸载,merged 目录变回空壳。

你可以用 mount 命令自己体验,mount -t overlay overlay -o lowerdir=/lower,upperdir=/upper,workdir=/work /merged

4.4 容器镜像构建流程与 Dockerfile 解析

Dockerfile 的每一条指令生成一层。层与层之间通过 OverlayFS 叠加,最终形成统一视图。

说一个很多人不知道的细节点:Dockerfile 中每条指令产生的中间层在最终镜像里是不存在的(被压缩成一个 layer)。但构建过程中,这些中间层对于构建缓存至关重要。docker build 的时候,每个指令执行完成后都会创建一个中间镜像,下一层如果没变,直接用缓存——这就是为什么把不常变化的层放上面(比如 apt-get install),经常变化的层放下面(比如 COPY . /app),可以大幅加速构建。

写 Dockerfile 的时候要记住,Dockerfile 的每一层都是不可变的!!!已经创建的层无法修改,只能在上面叠加新层。如果你发现基础镜像某个层的配置不对,只能重新构建整个镜像。

4.5 容器读写操作的透明性与性能优化

写时复制确实节省了存储,但频繁写小文件时有性能代价。每次对只读层文件的修改都要触发一次拷贝操作——把文件从 lowerdir 拷贝到 upperdir。

实际经验中,日志密集型应用放 OverlayFS 上性能下降非常明显。最佳实践是用 volume 把频繁读写的目录(比如 /var/log、数据库数据目录)挂载到容器外的独立存储上,绕过 OverlayFS 的写时复制。

五、容器生命周期

5.1 容器创建

容器创建三步曲:命名空间隔离 → Cgroups 资源限制 → 根文件系统挂载,这三个步骤是有严格顺序的,每一步之间都有依赖,任何一个步骤出错都会导致容器创建失败。容器运行时执行 docker run,背后内核做的核心工作就这三件,按顺序走:

第一步:Namespace 隔离。 调用 clone() 或 unshare() 创建新的 Namespace 集合——PID、Mount、Network、UTS、IPC 等,进程被丢进隔离环境。

第二步:Cgroups 资源限制。 在 cgroupfs 里创建子组,写入资源配额值,把进程 PID 写入 cgroup.procs 文件。从这一刻起,这个进程组的资源使用被内核严格监控。

第三步:根文件系统挂载。 用 OverlayFS 把镜像层和可写层组装成 merged 目录,pivot_root 或 chroot 到这个目录。内核层面,Docker Daemon 先通过 OverlayFS 将镜像只读层与容器读写层组装为 merged 目录,再通过 pivot_root 为容器进程切换根文件系统,之后执行 /proc/sys/dev 等关键虚拟文件系统的挂载,确保容器内拥有一个“完整系统”该有的基础环境

5.2 容器启动

容器的“第一个进程”(PID 1)是怎么来的?

答案是 clone() 系统调用

clone()系统调用通过传入 CLONE_NEWPID、CLONE_NEWNS、CLONE_NEWNET 等参数,创建各种命名空间 ,为容器构建独立的运行环境。例如,当设置 CLONE_NEWPID 参数时,会创建一个新的 PID 命名空间,在这个命名空间内,容器的 init 进程(初始化进程)的 PID 为 1 ,就像在独立的操作系统中一样 。

调用 clone () 完成后,会在新创建的命名空间内执行 init 进程 。init 进程作为容器的首个进程,肩负着重要使命,它负责启动容器内的应用程序,并管理容器内的其他进程 。如果 init 进程终止,容器也会随之退出,就像城市的核心枢纽停止运转,整个城市也将陷入瘫痪 。在基于 systemd 的容器中,init 进程通常是 systemd,它会读取容器内的配置文件,启动各种服务和应用程序,确保容器能够正常运行 。

5.3 容器运行时的状态监控与资源统计

docker stats 能看到 CPU、内存、网络、IO 统计。

但数据是哪来的?

答案是 cgroup 里的 memory.currentcpu.stat 等文件,Docker 实时读取这些文件然后把值格式化输出。

也可以直接看文件:cat /sys/fs/cgroup/system.slice/docker-<container-id>.scope/memory.current,拿到的就是容器当前内存用量(字节)。

/proc/[PID]/cgroup 路径记录了一个进程归属的所有 cgroup,从文件的视角观察容器的资源管控状态非常直观。

5.4 容器销毁

docker stop 发 SIGTERM,超时后 SIGKILL。

进程死亡后,Docker会从 cgroup 中移除进程 PID,删除该子 cgroup 目录;卸载 OverlayFS 的 merged 挂载点;释放容器写入层(upperdir)的存储空间;清除对应的 Network Namespace 和 veth pair。

这里需要注意的是,docker rm 而不是 docker stop 才会触发上层(可写层)数据的回收。你 docker stop 但不 docker rm,数据一直留在磁盘上——这些“死容器”多了会把磁盘吃满。我就经历过一次,一台服务器上留了四五百个 stopped 容器,docker system prune -a 清出了 40G 空间。所以说容器生命周期管理的最后一步(清理)才是很多人忽视的关键环节,不然你的 /var/lib/docker 会无限膨胀。

5.5 容器持久化存储与数据卷管理

由于容器的可写层在容器销毁后会被删除,若想保留容器运行过程中产生的数据(如数据库数据、日志文件等),就需要借助持久化存储技术,而数据卷(Volume)正是实现这一需求的核心方案。数据卷通过将宿主机目录或分布式存储挂载到容器内,让容器内的数据读写直接作用于持久化存储介质,即使容器销毁,数据也能得以保留。

Docker 支持三种主要的挂载方式:

第一种是 bind mount(绑定挂载),直接将宿主机的某个目录或文件挂载到容器内指定路径,例如 “docker run -v /host/path:/container/path ubuntu”,这条命令将宿主机的 /host/path 目录挂载到容器的 /container/path 目录,容器内对该目录的所有操作,都会直接同步到宿主机对应目录,适合需要直接访问宿主机文件的场景。

第二种是 volume(数据卷),这是 Docker 推荐的持久化方式。数据卷由 Docker 统一管理,默认存储在宿主机的 /var/lib/docker/volumes 目录下,用户无需关心具体的存储路径。例如,“docker volume create my-volume” 可以创建一个名为 my-volume 的数据卷,再通过 “docker run -v my-volume:/container/path ubuntu” 将其挂载到容器,数据卷可以被多个容器共享,且即使挂载的容器销毁,数据卷本身和其中的数据依然保留,需要手动删除。

第三种是 tmpfs mount(临时文件系统挂载),将数据存储在宿主机的内存中,而非磁盘上。这种方式的优势是读写速度极快,但数据在容器销毁或宿主机重启后会丢失,适合存储临时数据、缓存等无需持久化的内容,例如 “docker run --tmpfs /tmp ubuntu”,将容器的 /tmp 目录挂载为临时文件系统。

在 Kubernetes 集群环境中,数据卷的管理更加灵活,通过 PVC(Persistent Volume Claim,持久化卷声明)和 PV(Persistent Volume,持久化卷)机制,实现了数据卷的动态分配和管理。PV 由管理员提前创建,定义了存储资源的类型、大小等属性;PVC 由用户创建,用于申请所需的存储资源,系统会自动匹配符合条件的 PV 并进行绑定,无需用户手动关联存储设备,极大地简化了容器持久化存储的配置流程,满足大规模容器集群的存储需求。

六、容器网络

每个容器都有自己的网络命名空间(Network Namespace),里面装着独立的网络接口、IP、路由表、ARP表和iptables规则——就像一台迷你物理机。这样,容器和宿主机、容器和容器之间就实现了网络隔离。

6.1 容器网络模型

容器网络遵循OCI标准,所以Docker、Podman这些引擎的行为都一致。默认情况下,容器会拿到一个私有IP(通常来自Docker网桥的172.17.0.0/16网段),这个IP只在它自己的命名空间里有效,外面访问不了。要和外界通信,得靠宿主机的网络转发或端口映射。

除了默认的桥接模式,还有几种常用模式:

  • • 主机模式(--net=host):不创建独立命名空间,直接共享宿主机的网络栈,容器的IP和宿主机一样。适合需要直接使用宿主机网络资源的场景。
  • • none模式(--net=none):不给任何网络配置,完全手动。适合对隔离要求极高、根本不需要联网的容器。
  • • 容器模式(--net=container:容器ID):让新容器跟另一个容器共享同一个网络命名空间。

6.2 虚拟以太网桥接(veth pair)

容器跟宿主机、容器跟容器之间怎么通信?靠veth pair。

它就是一端插在容器里(通常叫eth0),另一端插在宿主机上的网桥或网络命名空间里,像一根虚拟网线,数据能来回传。

拿Docker默认的桥接模式来说,宿主机上有个叫docker0的网桥。每个容器启动时,veth pair的一端连到容器的eth0,另一端连到docker0。容器要跟宿主机通信,数据从eth0出发,穿过veth pair到docker0,再由docker0转发给宿主机的网卡。双向都能走,而且只在两个命名空间之间有效。既隔离,又能通。

6.3 容器间通信

同一台宿主机上的容器:默认走docker0网桥。所有连到docker0的容器都在同一个网段,二层交换(靠MAC地址)就能直接通信。比如容器A的IP是172.17.0.2,B是172.17.0.3,A直接ping B就行,数据不用经过宿主机的对外网卡,效率很高。

如果想做更细的隔离,可以自己建网桥:docker network create my-bridge,启动容器时指定--network my-bridge。不同网桥下的容器互相看不到,只有同一个网桥里的才能通。适合把不同业务隔离到不同的网络环境里。

跨宿主机的容器:光靠网桥不行,得用覆盖网络(Overlay Network)。常见的网络插件有Calico、Flannel、Weave等。它们通过在宿主机之间建隧道(比如VXLAN),把所有宿主机上的容器拉进同一个虚拟网络。比如Flannel会给每台宿主机分配一个独立网段,容器的IP从里面取,跨主机的通信就像在本地一样。

6.4 容器网络隔离与安全策略(如iptables)

网络隔离不光靠命名空间,还得靠安全策略,iptables是Linux自带的防火墙,能控制数据包的进出,Docker会自动配好iptables规则。比如你执行docker run -p 8080:80 nginx,Docker会在nat表里加一条端口转发规则,把宿主机的8080转到容器的80,同时在filter表里允许外部流量访问8080,禁止直接访问容器内部。

你也可以手动配,比如想禁止某个容器上网,就用iptables限制它的出站流量;想禁止不同网段的容器互相通信,就在filter表里加拒绝规则。总之,只开必要的端口,减少风险。

更高端的方案像Calico还支持网络策略(Network Policy),能基于容器标签做精细化访问控制,比如指定哪些容器可以访问当前容器的哪些端口。

6.5 高级网络方案:Service Mesh

容器规模一大,通信管理就变得复杂。

Service Mesh(服务网格)它通过Sidecar代理接管容器的所有网络流量,实现流量治理、熔断、限流、监控等功能,而且对业务代码无侵入。

以Istio为例,它会为每个容器注入一个Envoy Sidecar代理。容器间的所有通信都经过这个代理。代理负责转发流量、执行安全策略、收集数据。比如某个服务挂了,Sidecar自动把流量切到健康的实例;或者配置限流规则,防止服务被冲垮。

七、容器安全

7.1 Linux Capabilities:最小权限原则与权限控制

Linux里root权限太大了,如果容器里的进程是root,一旦容器逃逸,攻击者就拿到了宿主机的root。Linux Capabilities把root权限拆成一个个小单元,让容器只拿必要的权限,遵循最小权限原则。

常用的Capabilities单元:CAP_NET_BIND_SERVICE允许绑定小于1024的端口,CAP_CHOWN允许修改文件所有者,CAP_KILL允许杀进程等。默认容器只带了部分基础权限,你可以按需增减。

在Docker里,用--cap-add--cap-drop来调整。比如启动Nginx需要绑定80端口:docker run --cap-add=CAP_NET_BIND_SERVICE nginx。如果容器不需要改文件所有者,就--cap-drop=CAP_CHOWN。这样即使容器被攻破,攻击者也干不了太多事。

7.2 Seccomp:系统调用白名单与攻击防护

Seccomp(Secure Computing Mode)限制进程能执行的系统调用。攻击者常滥用危险系统调用(如fork、execve、mount)来突破容器。Seccomp配置白名单,只允许必要的调用(如read、write、open),禁止危险的。

Docker默认启用了Seccomp,已经禁止了fork、mount、umount等。你也可以自定义。比如一个只提供静态网页的容器,根本不需要execve和fork,就在配置里把它们禁掉。攻击者想用这些调用时,会被Seccomp直接拦住。

7.3 AppArmor与SELinux:强制访问控制(MAC)

AppArmor和SELinux是Linux的强制访问控制(MAC)机制,比自主访问控制更严格。

  • • AppArmor:基于路径的策略。比如给Nginx容器配个策略,禁止它访问宿主机的/etc/shadow/proc/sys。即使容器里是root,也碰不到这些敏感文件。
  • • SELinux:基于标签的策略。给每个文件、进程、设备打标签,然后配置标签间的访问规则。比如给容器进程打个标签,宿主机敏感文件打另一个标签,规则规定容器标签不能访问敏感文件标签。

Docker里用--security-opt启用这些策略。Ubuntu默认用AppArmor,CentOS默认用SELinux,你按需配置就行。

7.4 命名空间逃逸与内核漏洞防护

命名空间逃逸是容器安全的核心风险——攻击者利用内核漏洞或配置不当,突破命名空间,拿到宿主机权限。常见方式:内核漏洞(如Dirty COW)、滥用Mount Namespace挂载宿主机目录、通过User Namespace提权等。

防护手段:

  • • 及时更新内核补丁。厂商会修漏洞,比如Dirty COW,打个补丁就解决了。
  • • 规范容器配置。千万别用--privileged(特权模式),那会放开所有Capabilities,几乎等于没有隔离。限制挂载权限,别让容器挂载宿主机的//etc/proc。合理配置User Namespace,把容器里的root映射到宿主机的普通用户。
  • • **用安全监控工具(如Falco)**实时检测异常系统调用、非法挂载、提权尝试等,发现异常就报警并终止容器。

7.5 容器镜像安全:漏洞扫描与签名验证

镜像不安全,容器就别想安全。镜像可能带基础镜像漏洞、应用依赖漏洞、甚至恶意代码。

漏洞扫描:工具如Trivy、Clair、Aqua Security会扫描镜像每一层,找出系统漏洞和应用漏洞,给出严重等级和修复建议。Trivy可以集成到CI/CD里,在构建镜像时自动扫描,从源头堵住漏洞。

签名验证:防止镜像被篡改。发布者用私钥给镜像签名,用户拉取时用公钥验证。Docker Content Trust(DCT)就干这事。启用DCT后,只拉取经过签名的可信镜像。

另外,用官方或可信的基础镜像,定期更新依赖包,删除镜像里不必要的组件,减少攻击面。

八、内核如何“协同”这3大技术,启动一个容器?

8.1 步骤流程

我来按时间线拆一个容器的诞生过程。

以 docker run -it ubuntu:22.04 /bin/bash 为例,从敲下命令到容器进程启动,内核和 Docker Daemon 在这段极短的时间里完成了数十项操作。

  1. 1. Docker CLI 把请求发给 Docker Daemon(通过 Unix Socket 或 TCP)。
  2. 2. Daemon 检查本地有没有 ubuntu:22.04 镜像。没有就去 registry 拉。拉的过程中要解压镜像层、验证 checksum、存储到本地。
  3. 3. Daemon 创建容器的 OverlayFS 层结构——用已有的镜像只读层作为 lowerdir,创建新的 upperdir 作为容器写入层,建 workdir,挂载 merged 目录。
  4. 4. 在 cgroupfs 里创建新的控制组(通常路径类似 /sys/fs/cgroup/system.slice/docker-<container-id>.scope/),写入 CPU、内存等限制值。
  5. 5. 创建 Network Namespace,配置 veth pair,把 veth 的一端加入 docker0 网桥,另一端放入容器的 Network Namespace 并重命名为 eth0,分配 IP 地址,配置路由。
  6. 6. 调用 clone() 创建新进程,带上所有需要的 CLONE_NEW* 旗标,子进程进入全新的 Namespace 集合。
  7. 7. 在子进程内部,pivot_root 到 merged 目录,挂载 /proc/sys/dev/pts 等必要的虚拟文件系统。然后把子进程的 PID 写入步骤 4 创建的控制组的 cgroup.procs 文件。
  8. 8. 子进程 exec 用户指定的命令——/bin/bash。容器进程正式上线。
  9. 9. Daemon 收集容器进程的 stdout/stderr(通过管道),让你在终端上看到交互输出。

8.2 关键节点

四个节点依次执行:创建命名空间 → 配置Cgroups → 挂载UnionFS → 启动init进程。(命名空间划边界,Cgroups设上限,UnionFS给环境,init进程跑应用。)

  • • 创建命名空间:这是容器的骨架。内核不再告诉你这个进程只是宿主机上无数进程中的一员,而是给了它一个“只属于自己的世界”的幻象。
  • • 配置 Cgroups 资源限制:用文件操作完成。容器运行时在 cgroupfs 里写数字,内核调度器看到这些数字后会开始限制进程组的资源使用。没有这一步,一个内存泄漏的容器可以让整台机器瘫痪。
  • • 挂载 UnionFS(OverlayFS) :通过 mount 系统调用完成。内核把多个目录叠成单个目录,容器的 rootfs 呈现在进程面前。而且镜像层只有只读,所有修改都在独立的可写层。
  • • 启动 init 进程:靠 clone + exec 组合完成。新进程带全套 Namespace 出生,然后内核移交控制权给用户空间的应用,容器就算“活了”。

8.3 内核调用

容器启动本质上就是几个系统调用的协同。

  • • clone():创建新进程,同时通过标志位为新进程创建命名空间。比如CLONE_NEWPID给新PID命名空间,CLONE_NEWNET给新网络命名空间,CLONE_NEWNS给新Mount命名空间。调用完成后,新进程就在隔离环境里跑了。
  • • mount():负责挂载文件系统。容器启动时,mount要做两件事:一是挂载UnionFS,把只读层(lowerdir)和可写层(upperdir)叠加到容器的根目录;二是挂载数据卷(如果有),把宿主机目录或分布式存储挂载到容器内指定路径。得益于Mount Namespace,这些挂载只影响当前容器。
  • • cgroupfs相关系统调用:Cgroups以文件系统形式暴露在/sys/fs/cgroup下。通过mkdir在对应子系统下创建控制组目录,用write把配额(如CPU的50000)写入cpu.cfs_quota_us,再用attach_task把容器进程挂进去,资源限制就生效了。

三个调用的协同逻辑:clone()造隔离环境,mount()搭文件系统,cgroupfs设资源上限。

理解了它们怎么配合,你就摸清了容器底层的门道,排障、优化、安全防护都有了基础。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 16:37:39 HTTP/2.0 GET : https://f.mffb.com.cn/a/494432.html
  2. 运行时间 : 0.085734s [ 吞吐率:11.66req/s ] 内存消耗:4,487.35kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=31670c585d33b50c83b4b0a3b01e0963
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000659s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000906s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000293s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000301s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000468s ]
  6. SELECT * FROM `set` [ RunTime:0.000198s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000506s ]
  8. SELECT * FROM `article` WHERE `id` = 494432 LIMIT 1 [ RunTime:0.001349s ]
  9. UPDATE `article` SET `lasttime` = 1783067859 WHERE `id` = 494432 [ RunTime:0.000921s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000216s ]
  11. SELECT * FROM `article` WHERE `id` < 494432 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000442s ]
  12. SELECT * FROM `article` WHERE `id` > 494432 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000361s ]
  13. SELECT * FROM `article` WHERE `id` < 494432 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002306s ]
  14. SELECT * FROM `article` WHERE `id` < 494432 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.008102s ]
  15. SELECT * FROM `article` WHERE `id` < 494432 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001875s ]
0.087345s